diff --git a/dep-graph/client/src/app/machines/dep-graph.spec.ts b/dep-graph/client/src/app/machines/dep-graph.spec.ts index ae639c4760..d6993473fd 100644 --- a/dep-graph/client/src/app/machines/dep-graph.spec.ts +++ b/dep-graph/client/src/app/machines/dep-graph.spec.ts @@ -1,9 +1,12 @@ // nx-ignore-next-line -import type { ProjectGraphDependency, ProjectGraphNode } from '@nrwl/devkit'; +import type { + ProjectGraphDependency, + ProjectGraphProjectNode, +} from '@nrwl/devkit'; import { depGraphMachine } from './dep-graph.machine'; import { interpret } from 'xstate'; -export const mockProjects: ProjectGraphNode[] = [ +export const mockProjects: ProjectGraphProjectNode[] = [ { name: 'app1', type: 'app', diff --git a/dep-graph/client/src/app/machines/graph.ts b/dep-graph/client/src/app/machines/graph.ts index fb8fe8415b..c22da2a4c5 100644 --- a/dep-graph/client/src/app/machines/graph.ts +++ b/dep-graph/client/src/app/machines/graph.ts @@ -1,5 +1,8 @@ // nx-ignore-next-line -import type { ProjectGraphDependency, ProjectGraphNode } from '@nrwl/devkit'; +import type { + ProjectGraphDependency, + ProjectGraphProjectNode, +} from '@nrwl/devkit'; import type { VirtualElement } from '@popperjs/core'; import { default as cy } from 'cytoscape'; import { default as cytoscapeDagre } from 'cytoscape-dagre'; @@ -323,7 +326,7 @@ export class GraphService { } initGraph( - allProjects: ProjectGraphNode[], + allProjects: ProjectGraphProjectNode[], groupByFolder: boolean, workspaceLayout, dependencies: Record, @@ -341,7 +344,7 @@ export class GraphService { } private generateCytoscapeLayout( - allProjects: ProjectGraphNode[], + allProjects: ProjectGraphProjectNode[], groupByFolder: boolean, workspaceLayout, dependencies: Record, @@ -364,7 +367,7 @@ export class GraphService { } private createElements( - projects: ProjectGraphNode[], + projects: ProjectGraphProjectNode[], groupByFolder: boolean, workspaceLayout: { appsDir: string; diff --git a/dep-graph/client/src/app/machines/interfaces.ts b/dep-graph/client/src/app/machines/interfaces.ts index c4e2756e25..b2674c6b4f 100644 --- a/dep-graph/client/src/app/machines/interfaces.ts +++ b/dep-graph/client/src/app/machines/interfaces.ts @@ -1,5 +1,8 @@ // nx-ignore-next-line -import type { ProjectGraphDependency, ProjectGraphNode } from '@nrwl/devkit'; +import type { + ProjectGraphDependency, + ProjectGraphProjectNode, +} from '@nrwl/devkit'; import { ActionObject, ActorRef, State, StateNodeConfig } from 'xstate'; // The hierarchical (recursive) schema for the states @@ -43,7 +46,7 @@ export type DepGraphUIEvents = | { type: 'clearTextFilter' } | { type: 'initGraph'; - projects: ProjectGraphNode[]; + projects: ProjectGraphProjectNode[]; dependencies: Record; affectedProjects: string[]; workspaceLayout: { @@ -53,7 +56,7 @@ export type DepGraphUIEvents = } | { type: 'updateGraph'; - projects: ProjectGraphNode[]; + projects: ProjectGraphProjectNode[]; dependencies: Record; }; @@ -62,7 +65,7 @@ export type DepGraphUIEvents = export type GraphRenderEvents = | { type: 'notifyGraphInitGraph'; - projects: ProjectGraphNode[]; + projects: ProjectGraphProjectNode[]; dependencies: Record; affectedProjects: string[]; workspaceLayout: { @@ -73,7 +76,7 @@ export type GraphRenderEvents = } | { type: 'notifyGraphUpdateGraph'; - projects: ProjectGraphNode[]; + projects: ProjectGraphProjectNode[]; dependencies: Record; affectedProjects: string[]; workspaceLayout: { @@ -141,7 +144,7 @@ export type AllEvents = DepGraphUIEvents | GraphRenderEvents | RouteEvents; // The context (extended state) of the machine export interface DepGraphContext { - projects: ProjectGraphNode[]; + projects: ProjectGraphProjectNode[]; dependencies: Record; affectedProjects: string[]; selectedProjects: string[]; diff --git a/dep-graph/client/src/app/machines/selectors.ts b/dep-graph/client/src/app/machines/selectors.ts index d9143a9d58..9b95b741c7 100644 --- a/dep-graph/client/src/app/machines/selectors.ts +++ b/dep-graph/client/src/app/machines/selectors.ts @@ -1,11 +1,11 @@ -import type { ProjectGraphNode } from '@nrwl/devkit'; +import type { ProjectGraphProjectNode } from '@nrwl/devkit'; import { DepGraphSelector } from '../hooks/use-dep-graph-selector'; import { WorkspaceLayout } from '../interfaces'; import { GraphPerfReport } from './interfaces'; -export const allProjectsSelector: DepGraphSelector = ( - state -) => state.context.projects; +export const allProjectsSelector: DepGraphSelector< + ProjectGraphProjectNode[] +> = (state) => state.context.projects; export const workspaceLayoutSelector: DepGraphSelector = ( state diff --git a/dep-graph/client/src/app/mock-project-graph-service.ts b/dep-graph/client/src/app/mock-project-graph-service.ts index 7911fd6574..d385756252 100644 --- a/dep-graph/client/src/app/mock-project-graph-service.ts +++ b/dep-graph/client/src/app/mock-project-graph-service.ts @@ -1,4 +1,7 @@ -import type { ProjectGraphDependency, ProjectGraphNode } from '@nrwl/devkit'; +import type { + ProjectGraphDependency, + ProjectGraphProjectNode, +} from '@nrwl/devkit'; // nx-ignore-next-line import type { DepGraphClientResponse } from '@nrwl/workspace/src/command-line/dep-graph'; import { ProjectGraphService } from '../app/interfaces'; @@ -56,7 +59,7 @@ export class MockProjectGraphService implements ProjectGraphService { return new Promise((resolve) => resolve(this.response)); } - private createNewProject(): ProjectGraphNode { + private createNewProject(): ProjectGraphProjectNode { const type = Math.random() > 0.25 ? 'lib' : 'app'; const name = `${type}-${this.response.projects.length + 1}`; diff --git a/dep-graph/client/src/app/util-cytoscape/project-node.ts b/dep-graph/client/src/app/util-cytoscape/project-node.ts index d5de5d45d2..fe249389dd 100644 --- a/dep-graph/client/src/app/util-cytoscape/project-node.ts +++ b/dep-graph/client/src/app/util-cytoscape/project-node.ts @@ -1,4 +1,4 @@ -import type { ProjectGraphNode } from '@nrwl/devkit'; +import type { ProjectGraphProjectNode } from '@nrwl/devkit'; import * as cy from 'cytoscape'; import { parseParentDirectoriesFromPilePath } from '../util'; @@ -18,7 +18,7 @@ export class ProjectNode { focused = false; constructor( - private project: ProjectGraphNode, + private project: ProjectGraphProjectNode, private workspaceRoot: string ) {} diff --git a/docs/generated/api-nx-devkit/index.md b/docs/generated/api-nx-devkit/index.md index c2abb4f5b4..7ed39fe768 100644 --- a/docs/generated/api-nx-devkit/index.md +++ b/docs/generated/api-nx-devkit/index.md @@ -40,6 +40,7 @@ It only uses language primitives and immutable objects - [ProjectGraphExternalNode](../../nx-devkit/index#projectgraphexternalnode) - [ProjectGraphProcessorContext](../../nx-devkit/index#projectgraphprocessorcontext) - [ProjectGraphProjectNode](../../nx-devkit/index#projectgraphprojectnode) +- [ProjectGraphV4](../../nx-devkit/index#projectgraphv4) ### Tree Interfaces @@ -240,6 +241,18 @@ A plugin for Nx --- +### ProjectGraphV4 + +• **ProjectGraphV4**<`T`\>: `Object` + +#### Type parameters + +| Name | Type | +| :--- | :---- | +| `T` | `any` | + +--- + ## Tree Interfaces ### FileChange diff --git a/packages/devkit/index.ts b/packages/devkit/index.ts index a306950c24..a31bec3982 100644 --- a/packages/devkit/index.ts +++ b/packages/devkit/index.ts @@ -144,6 +144,7 @@ export type { ProjectFileMap, FileData, ProjectGraph, + ProjectGraphV4, ProjectGraphDependency, ProjectGraphNode, ProjectGraphProjectNode, diff --git a/packages/devkit/src/project-graph/project-graph-builder.ts b/packages/devkit/src/project-graph/project-graph-builder.ts index b97bafc316..1c2410cdbf 100644 --- a/packages/devkit/src/project-graph/project-graph-builder.ts +++ b/packages/devkit/src/project-graph/project-graph-builder.ts @@ -2,7 +2,7 @@ import type { ProjectGraph, ProjectGraphDependency, ProjectGraphExternalNode, - ProjectGraphNode, + ProjectGraphProjectNode, } from './interfaces'; import { DependencyType } from './interfaces'; @@ -28,7 +28,7 @@ export class ProjectGraphBuilder { /** * Adds a project node to the project graph */ - addNode(node: ProjectGraphNode): void { + addNode(node: ProjectGraphProjectNode): void { // Check if project with the same name already exists if (this.graph.nodes[node.name]) { // Throw if existing project is of a different type diff --git a/packages/tao/src/shared/project-graph.ts b/packages/tao/src/shared/project-graph.ts index ebc03b7e1e..75618ceeeb 100644 --- a/packages/tao/src/shared/project-graph.ts +++ b/packages/tao/src/shared/project-graph.ts @@ -25,7 +25,7 @@ export interface ProjectFileMap { * A Graph of projects in the workspace and dependencies between them */ export interface ProjectGraph { - nodes: Record>; + nodes: Record>; externalNodes?: Record; dependencies: Record; // this is optional otherwise it might break folks who use project graph creation @@ -33,6 +33,14 @@ export interface ProjectGraph { version?: string; } +export interface ProjectGraphV4 { + nodes: Record>; + dependencies: Record; + // this is optional otherwise it might break folks who use project graph creation + allWorkspaceFiles?: FileData[]; + version?: string; +} + /** * Type of dependency between projects */ @@ -52,7 +60,7 @@ export enum DependencyType { } /** - * A node describing a node in a workspace + * A node describing a project or an external node in a workspace */ export type ProjectGraphNode = | ProjectGraphProjectNode diff --git a/packages/web/src/executors/rollup/rollup.impl.ts b/packages/web/src/executors/rollup/rollup.impl.ts index c8047b5b53..73749eb020 100644 --- a/packages/web/src/executors/rollup/rollup.impl.ts +++ b/packages/web/src/executors/rollup/rollup.impl.ts @@ -6,8 +6,11 @@ import { from, Observable, of } from 'rxjs'; import { catchError, concatMap, last, scan, tap } from 'rxjs/operators'; import { eachValueFrom } from 'rxjs-for-await'; import * as autoprefixer from 'autoprefixer'; - -import type { ExecutorContext, ProjectGraphNode } from '@nrwl/devkit'; +import type { + ExecutorContext, + ProjectGraphExternalNode, + ProjectGraphProjectNode, +} from '@nrwl/devkit'; import { logger, names, readJsonFile, writeJsonFile } from '@nrwl/devkit'; import { readCachedProjectGraph } from '@nrwl/workspace/src/core/project-graph'; import { @@ -320,7 +323,7 @@ function createCompilerOptions(format, options, dependencies) { function updatePackageJson( options: NormalizedWebRollupOptions, context: ExecutorContext, - target: ProjectGraphNode, + target: ProjectGraphProjectNode, dependencies: DependentBuildableProjectNode[], packageJson: any ) { diff --git a/packages/workspace/src/command-line/affected.ts b/packages/workspace/src/command-line/affected.ts index 5cae7fff92..0304cf84ec 100644 --- a/packages/workspace/src/command-line/affected.ts +++ b/packages/workspace/src/command-line/affected.ts @@ -3,14 +3,11 @@ import { filterAffected } from '../core/affected-project-graph'; import { calculateFileChanges, readEnvironment } from '../core/file-utils'; import { createProjectGraphAsync, + ProjectGraphNodeRecords, ProjectType, withDeps, } from '../core/project-graph'; -import { - ProjectGraph, - ProjectGraphNode, - ProjectGraphProjectNode, -} from '@nrwl/devkit'; +import { ProjectGraph, ProjectGraphProjectNode } from '@nrwl/devkit'; import { runCommand } from '../tasks-runner/run-command'; import { output } from '../utilities/output'; import { projectHasTarget } from '../utilities/project-graph-utils'; @@ -123,7 +120,10 @@ export async function affected( } } -function projectsToRun(nxArgs: NxArgs, projectGraph: ProjectGraph) { +function projectsToRun( + nxArgs: NxArgs, + projectGraph: ProjectGraph +): ProjectGraphProjectNode[] { let affectedGraph = nxArgs.all ? projectGraph : filterAffected( @@ -143,15 +143,18 @@ function projectsToRun(nxArgs: NxArgs, projectGraph: ProjectGraph) { if (nxArgs.exclude) { const excludedProjects = new Set(nxArgs.exclude); - return Object.entries(affectedGraph.nodes) + return Object.entries(affectedGraph.nodes as ProjectGraphNodeRecords) .filter(([projectName]) => !excludedProjects.has(projectName)) .map(([, project]) => project); } - return Object.values(affectedGraph.nodes); + return Object.values(affectedGraph.nodes) as ProjectGraphProjectNode[]; } -function allProjectsWithTarget(projects: ProjectGraphNode[], nxArgs: NxArgs) { +function allProjectsWithTarget( + projects: ProjectGraphProjectNode[], + nxArgs: NxArgs +) { return projects.filter((p) => projectHasTarget(p, nxArgs.target)); } diff --git a/packages/workspace/src/command-line/dep-graph.ts b/packages/workspace/src/command-line/dep-graph.ts index 4b8d93c818..7721033abe 100644 --- a/packages/workspace/src/command-line/dep-graph.ts +++ b/packages/workspace/src/command-line/dep-graph.ts @@ -8,7 +8,7 @@ import * as http from 'http'; import ignore from 'ignore'; import * as open from 'open'; import { basename, dirname, extname, isAbsolute, join, parse } from 'path'; -import { ProjectGraphProjectNode, writeJsonFile } from '@nrwl/devkit'; +import { writeJsonFile } from '@nrwl/devkit'; import { performance } from 'perf_hooks'; import { URL, URLSearchParams } from 'url'; import { workspaceLayout } from '../core/file-utils'; @@ -17,14 +17,14 @@ import { createProjectGraphAsync, ProjectGraph, ProjectGraphDependency, - ProjectGraphNode, + ProjectGraphProjectNode, pruneExternalNodes, } from '../core/project-graph'; import { output } from '../utilities/output'; export interface DepGraphClientResponse { hash: string; - projects: ProjectGraphNode[]; + projects: ProjectGraphProjectNode[]; dependencies: Record; layout: { appsDir: string; libsDir: string }; affected: string[]; @@ -61,7 +61,7 @@ function buildEnvironmentJs( window.watch = ${!!watchMode}; window.environment = 'release'; window.localMode = '${localMode}'; - + window.appConfig = { showDebugger: false, projectGraphs: [ @@ -86,7 +86,10 @@ function buildEnvironmentJs( return environmentJs; } -function projectExists(projects: ProjectGraphNode[], projectToFind: string) { +function projectExists( + projects: ProjectGraphProjectNode[], + projectToFind: string +) { return ( projects.find((project) => project.name === projectToFind) !== undefined ); @@ -113,9 +116,9 @@ function filterGraph( focus: string, exclude: string[] ): ProjectGraph { - let projectNames = (Object.values(graph.nodes) as ProjectGraphNode[]).map( - (project) => project.name - ); + let projectNames = ( + Object.values(graph.nodes) as ProjectGraphProjectNode[] + ).map((project) => project.name); let filteredProjectNames: Set; @@ -166,7 +169,7 @@ export async function generateGraph( let graph = pruneExternalNodes(await createProjectGraphAsync()); const layout = workspaceLayout(); - const projects = Object.values(graph.nodes) as ProjectGraphNode[]; + const projects = Object.values(graph.nodes) as ProjectGraphProjectNode[]; projects.sort((a, b) => { return a.name.localeCompare(b.name); }); diff --git a/packages/workspace/src/command-line/print-affected.ts b/packages/workspace/src/command-line/print-affected.ts index 336086dd39..00de536f33 100644 --- a/packages/workspace/src/command-line/print-affected.ts +++ b/packages/workspace/src/command-line/print-affected.ts @@ -1,4 +1,4 @@ -import { ProjectGraph, ProjectGraphNode, Task } from '@nrwl/devkit'; +import { ProjectGraph, ProjectGraphProjectNode, Task } from '@nrwl/devkit'; import type { Environment } from '../core/shared-interfaces'; import { createTask } from '../tasks-runner/run-command'; import { getCommandAsString, getOutputs } from '../tasks-runner/utils'; @@ -6,8 +6,8 @@ import * as yargs from 'yargs'; import type { NxArgs } from './utils'; export async function printAffected( - affectedProjectsWithTargetAndConfig: ProjectGraphNode[], - affectedProjects: ProjectGraphNode[], + affectedProjectsWithTargetAndConfig: ProjectGraphProjectNode[], + affectedProjects: ProjectGraphProjectNode[], projectGraph: ProjectGraph, { nxJson }: Environment, nxArgs: NxArgs, @@ -33,7 +33,7 @@ export async function printAffected( } async function createTasks( - affectedProjectsWithTargetAndConfig: ProjectGraphNode[], + affectedProjectsWithTargetAndConfig: ProjectGraphProjectNode[], projectGraph: ProjectGraph, nxArgs: NxArgs, overrides: yargs.Arguments diff --git a/packages/workspace/src/command-line/run-many.ts b/packages/workspace/src/command-line/run-many.ts index 09efa4d33a..f2e2486478 100644 --- a/packages/workspace/src/command-line/run-many.ts +++ b/packages/workspace/src/command-line/run-many.ts @@ -3,7 +3,7 @@ import { runCommand } from '../tasks-runner/run-command'; import type { NxArgs, RawNxArgs } from './utils'; import { splitArgsIntoNxArgsAndOverrides } from './utils'; import { createProjectGraphAsync } from '../core/project-graph'; -import type { ProjectGraph, ProjectGraphNode } from '@nrwl/devkit'; +import type { ProjectGraph, ProjectGraphProjectNode } from '@nrwl/devkit'; import { readEnvironment } from '../core/file-utils'; import { projectHasTarget } from '../utilities/project-graph-utils'; import { output } from '../utilities/output'; @@ -37,7 +37,7 @@ export async function runMany(parsedArgs: yargs.Arguments & RawNxArgs) { function projectsToRun( nxArgs: NxArgs, projectGraph: ProjectGraph -): ProjectGraphNode[] { +): ProjectGraphProjectNode[] { const allProjects = Object.values(projectGraph.nodes); const excludedProjects = new Set(nxArgs.exclude ?? []); if (nxArgs.all) { @@ -56,7 +56,7 @@ function projectsToRun( function checkForInvalidProjects( nxArgs: NxArgs, - allProjects: ProjectGraphNode[] + allProjects: ProjectGraphProjectNode[] ) { const invalid = nxArgs.projects.filter( (name) => !allProjects.find((p) => p.name === name) @@ -67,12 +67,12 @@ function checkForInvalidProjects( } function runnableForTarget( - projects: ProjectGraphNode[], + projects: ProjectGraphProjectNode[], target: string, strict = false -): ProjectGraphNode[] { - const notRunnable = [] as ProjectGraphNode[]; - const runnable = [] as ProjectGraphNode[]; +): ProjectGraphProjectNode[] { + const notRunnable = [] as ProjectGraphProjectNode[]; + const runnable = [] as ProjectGraphProjectNode[]; for (let project of projects) { if (projectHasTarget(project, target)) { diff --git a/packages/workspace/src/core/affected-project-graph/locators/tsconfig-json-changes.ts b/packages/workspace/src/core/affected-project-graph/locators/tsconfig-json-changes.ts index b8fe95c87d..360e33a4f7 100644 --- a/packages/workspace/src/core/affected-project-graph/locators/tsconfig-json-changes.ts +++ b/packages/workspace/src/core/affected-project-graph/locators/tsconfig-json-changes.ts @@ -5,7 +5,7 @@ import { JsonChange, } from '../../../utilities/json-diff'; import { TouchedProjectLocator } from '../affected-project-graph-models'; -import { ProjectGraphNode } from '../../project-graph'; +import { ProjectGraphProjectNode } from '../../project-graph'; export const getTouchedProjectsFromTsConfig: TouchedProjectLocator< WholeFileChange | JsonChange @@ -54,7 +54,7 @@ function allChangesArePathChanges( */ function getProjectsAffectedByPaths( change: JsonChange, - nodes: ProjectGraphNode[] + nodes: ProjectGraphProjectNode[] ) { const result = []; const paths: string[] = [change.value.lhs, change.value.rhs]; diff --git a/packages/workspace/src/core/file-utils.ts b/packages/workspace/src/core/file-utils.ts index 5449706f80..670ef2d084 100644 --- a/packages/workspace/src/core/file-utils.ts +++ b/packages/workspace/src/core/file-utils.ts @@ -3,11 +3,7 @@ import { WorkspaceJsonConfiguration, Workspaces, } from '@nrwl/tao/src/shared/workspace'; -import type { - FileData, - NxJsonConfiguration, - ProjectGraphNode, -} from '@nrwl/devkit'; +import type { FileData, NxJsonConfiguration } from '@nrwl/devkit'; import { readJsonFile } from '@nrwl/devkit'; import { execSync } from 'child_process'; import { existsSync, readFileSync } from 'fs'; diff --git a/packages/workspace/src/core/nx-deps/nx-deps-cache.spec.ts b/packages/workspace/src/core/nx-deps/nx-deps-cache.spec.ts index d3a466a53a..5c9e60d40a 100644 --- a/packages/workspace/src/core/nx-deps/nx-deps-cache.spec.ts +++ b/packages/workspace/src/core/nx-deps/nx-deps-cache.spec.ts @@ -1,4 +1,8 @@ -import { NxJsonConfiguration, WorkspaceJsonConfiguration } from '@nrwl/devkit'; +import { + NxJsonConfiguration, + ProjectGraph, + WorkspaceJsonConfiguration, +} from '@nrwl/devkit'; import { createCache as _createCache, extractCachedFileData, @@ -284,7 +288,7 @@ describe('nx deps utils', () => { _createCache( createNxJson({}), createPackageJsonDeps({}), - createCache({}), + createCache({}) as ProjectGraph, {} ); }); @@ -293,7 +297,7 @@ describe('nx deps utils', () => { const result = _createCache( createNxJson({}), createPackageJsonDeps({}), - createCache({}), + createCache({}) as ProjectGraph, undefined ); @@ -303,7 +307,7 @@ describe('nx deps utils', () => { function createCache(p: Partial): ProjectGraphCache { const defaults: ProjectGraphCache = { - version: '3.0', + version: '5.0', deps: { '@nrwl/workspace': '12.0.0', plugin: '1.0.0', diff --git a/packages/workspace/src/core/nx-deps/nx-deps-cache.ts b/packages/workspace/src/core/nx-deps/nx-deps-cache.ts index c79a659349..5517b5eb70 100644 --- a/packages/workspace/src/core/nx-deps/nx-deps-cache.ts +++ b/packages/workspace/src/core/nx-deps/nx-deps-cache.ts @@ -77,7 +77,7 @@ export function readCache(): null | ProjectGraphCache { export function createCache( nxJson: NxJsonConfiguration<'*' | string[]>, packageJsonDeps: Record, - projectGraph: ProjectGraph, + projectGraph: ProjectGraph, tsConfig: { compilerOptions?: { paths?: { [p: string]: any } } } ) { const nxJsonPlugins = (nxJson.plugins || []).map((p) => ({ diff --git a/packages/workspace/src/core/project-graph/build-dependencies/explicit-package-json-dependencies.spec.ts b/packages/workspace/src/core/project-graph/build-dependencies/explicit-package-json-dependencies.spec.ts index 5dda36f4ee..0ad9778d56 100644 --- a/packages/workspace/src/core/project-graph/build-dependencies/explicit-package-json-dependencies.spec.ts +++ b/packages/workspace/src/core/project-graph/build-dependencies/explicit-package-json-dependencies.spec.ts @@ -1,6 +1,6 @@ import { buildExplicitPackageJsonDependencies } from './explicit-package-json-dependencies'; import { vol } from 'memfs'; -import { ProjectGraphNode } from '../project-graph-models'; +import { ProjectGraphProjectNode } from '../project-graph-models'; import { ProjectGraphBuilder, ProjectGraphProcessorContext, @@ -15,7 +15,7 @@ jest.mock('@nrwl/tao/src/utils/app-root', () => ({ describe('explicit package json dependencies', () => { let ctx: ProjectGraphProcessorContext; - let projects: Record; + let projects: Record; let fsJson; beforeEach(() => { const workspaceJson = { diff --git a/packages/workspace/src/core/project-graph/build-dependencies/explicit-package-json-dependencies.ts b/packages/workspace/src/core/project-graph/build-dependencies/explicit-package-json-dependencies.ts index ed32e260bb..90da51492c 100644 --- a/packages/workspace/src/core/project-graph/build-dependencies/explicit-package-json-dependencies.ts +++ b/packages/workspace/src/core/project-graph/build-dependencies/explicit-package-json-dependencies.ts @@ -17,7 +17,12 @@ export function buildExplicitPackageJsonDependencies( let packageNameMap = undefined; Object.keys(filesToProcess).forEach((source) => { Object.values(filesToProcess[source]).forEach((f) => { - if (isPackageJsonAtProjectRoot(graph.nodes, f.file)) { + if ( + isPackageJsonAtProjectRoot( + graph.nodes as ProjectGraphNodeRecords, + f.file + ) + ) { // we only create the package name map once and only if a package.json file changes packageNameMap = packageNameMap || createPackageNameMap(workspace); processPackageJson(source, f.file, graph, res, packageNameMap); diff --git a/packages/workspace/src/core/project-graph/build-dependencies/explicit-project-dependencies.spec.ts b/packages/workspace/src/core/project-graph/build-dependencies/explicit-project-dependencies.spec.ts index 4892fd4a87..a6dac1acc7 100644 --- a/packages/workspace/src/core/project-graph/build-dependencies/explicit-project-dependencies.spec.ts +++ b/packages/workspace/src/core/project-graph/build-dependencies/explicit-project-dependencies.spec.ts @@ -6,7 +6,7 @@ jest.mock('@nrwl/tao/src/utils/app-root', () => ({ })); import { vol } from 'memfs'; -import { ProjectGraphNode } from '../project-graph-models'; +import { ProjectGraphProjectNode } from '../project-graph-models'; import { buildExplicitTypeScriptDependencies } from './explicit-project-dependencies'; import { ProjectGraphBuilder, @@ -16,7 +16,7 @@ import { defaultFileHasher } from '../../hasher/file-hasher'; describe('explicit project dependencies', () => { let ctx: ProjectGraphProcessorContext; - let projects: Record; + let projects: Record; let fsJson; beforeEach(() => { const workspaceJson = { diff --git a/packages/workspace/src/core/project-graph/build-dependencies/explicit-project-dependencies.ts b/packages/workspace/src/core/project-graph/build-dependencies/explicit-project-dependencies.ts index 7b49d2d5bb..bce3a2f306 100644 --- a/packages/workspace/src/core/project-graph/build-dependencies/explicit-project-dependencies.ts +++ b/packages/workspace/src/core/project-graph/build-dependencies/explicit-project-dependencies.ts @@ -1,12 +1,11 @@ -import { DependencyType, ProjectGraph } from '../project-graph-models'; +import { + DependencyType, + ProjectGraph, + ProjectGraphNodeRecords, +} from '../project-graph-models'; import { TypeScriptImportLocator } from './typescript-import-locator'; import { TargetProjectLocator } from '../../target-project-locator'; -import { - ProjectFileMap, - ProjectGraphBuilder, - ProjectGraphProcessorContext, - Workspace, -} from '@nrwl/devkit'; +import { ProjectFileMap, Workspace } from '@nrwl/devkit'; export function buildExplicitTypeScriptDependencies( workspace: Workspace, @@ -15,7 +14,7 @@ export function buildExplicitTypeScriptDependencies( ) { const importLocator = new TypeScriptImportLocator(); const targetProjectLocator = new TargetProjectLocator( - graph.nodes, + graph.nodes as ProjectGraphNodeRecords, graph.externalNodes ); const res = [] as any; 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 493d369f96..4acbd5ba54 100644 --- a/packages/workspace/src/core/project-graph/build-project-graph.ts +++ b/packages/workspace/src/core/project-graph/build-project-graph.ts @@ -3,7 +3,6 @@ import { logger, NxJsonConfiguration, NxJsonProjectConfiguration, - NxPlugin, ProjectConfiguration, ProjectFileMap, ProjectGraph, diff --git a/packages/workspace/src/core/project-graph/operators.ts b/packages/workspace/src/core/project-graph/operators.ts index 86f41a059c..a9f85adcdf 100644 --- a/packages/workspace/src/core/project-graph/operators.ts +++ b/packages/workspace/src/core/project-graph/operators.ts @@ -69,7 +69,9 @@ export function filterNodes( /** * @deprecated will be removed in v14. All projects in ProjectGraph's `nodes` are workspace projects */ -export function isWorkspaceProject(project: ProjectGraphNode) { +export function isWorkspaceProject( + project: ProjectGraphNode +): project is ProjectGraphProjectNode { return ( project.type === 'app' || project.type === 'lib' || project.type === 'e2e' ); diff --git a/packages/workspace/src/core/project-graph/project-graph-models.ts b/packages/workspace/src/core/project-graph/project-graph-models.ts index 69d43a1569..6660aff04b 100644 --- a/packages/workspace/src/core/project-graph/project-graph-models.ts +++ b/packages/workspace/src/core/project-graph/project-graph-models.ts @@ -1,13 +1,13 @@ -import type { DependencyType, ProjectGraphNode } from '@nrwl/devkit'; +import type { ProjectGraphProjectNode } from '@nrwl/devkit'; export { ProjectGraph, ProjectGraphDependency, - ProjectGraphNode, + ProjectGraphProjectNode, DependencyType, } from '@nrwl/devkit'; -export type ProjectGraphNodeRecords = Record; +export type ProjectGraphNodeRecords = Record; export enum ProjectType { app = 'app', diff --git a/packages/workspace/src/core/project-graph/project-graph.ts b/packages/workspace/src/core/project-graph/project-graph.ts index c77270c5d6..bb78243634 100644 --- a/packages/workspace/src/core/project-graph/project-graph.ts +++ b/packages/workspace/src/core/project-graph/project-graph.ts @@ -1,4 +1,4 @@ -import { ProjectGraph, stripIndents } from '@nrwl/devkit'; +import { ProjectGraph, ProjectGraphV4, stripIndents } from '@nrwl/devkit'; import { ProjectGraphCache, readCache } from '../nx-deps/nx-deps-cache'; import { buildProjectGraph } from './build-project-graph'; import { readNxJson, workspaceFileName } from '../file-utils'; @@ -16,9 +16,7 @@ import { lstatSync, statSync } from 'fs'; * Synchronously reads the latest cached copy of the workspace's ProjectGraph. * @throws {Error} if there is no cached ProjectGraph to read from */ -export function readCachedProjectGraph( - projectGraphVersion = '5.0' -): ProjectGraph { +export function readCachedProjectGraph(): ProjectGraph { const projectGraphCache: ProjectGraphCache | false = readCache(); const angularSpecificError = workspaceFileName() === 'angular.json' @@ -45,32 +43,26 @@ export function readCachedProjectGraph( nodes: projectGraphCache.nodes, externalNodes: projectGraphCache.externalNodes, dependencies: projectGraphCache.dependencies, - }; + } as ProjectGraph; return projectGraphAdapter( projectGraph.version, - projectGraphVersion, + '5.0', projectGraph - ); + ) as ProjectGraph; } -async function buildProjectGraphWithoutDaemon(projectGraphVersion: string) { +async function buildProjectGraphWithoutDaemon() { try { await defaultFileHasher.ensureInitialized(); - return projectGraphAdapter( - '5.0', - projectGraphVersion, - await buildProjectGraph() - ); + return await buildProjectGraph(); } catch (e) { printErrorMessage(e); process.exit(1); } } -export async function createProjectGraphAsync( - projectGraphVersion = '5.0' -): Promise { +export async function createProjectGraphAsync(): Promise { const nxJson = readNxJson(); const useDaemonProcessOption = nxJson.tasksRunnerOptions?.['default']?.options?.useDaemonProcess; @@ -93,18 +85,14 @@ export async function createProjectGraphAsync( (useDaemonProcessOption === false && env === undefined) || (useDaemonProcessOption === false && env === 'false') ) { - return await buildProjectGraphWithoutDaemon(projectGraphVersion); + return await buildProjectGraphWithoutDaemon(); } else { try { const daemonClient = require('./daemon/client/client'); if (!(await daemonClient.isServerAvailable())) { await daemonClient.startInBackground(); } - return projectGraphAdapter( - '5.0', - projectGraphVersion, - await daemonClient.getProjectGraphFromServer() - ); + return daemonClient.getProjectGraphFromServer(); } catch (e) { if (e.message.indexOf('inotify_add_watch') > -1) { // common errors with the daemon due to OS settings (cannot watch all the files available) @@ -127,7 +115,7 @@ export async function createProjectGraphAsync( }); } markDaemonAsDisabled(); - return buildProjectGraphWithoutDaemon(projectGraphVersion); + return buildProjectGraphWithoutDaemon(); } } } @@ -161,12 +149,12 @@ export function projectGraphAdapter( sourceVersion: string, targetVersion: string, projectGraph: ProjectGraph -): ProjectGraph { +): ProjectGraph | ProjectGraphV4 { if (sourceVersion === targetVersion) { return projectGraph; } if (sourceVersion === '5.0' && targetVersion === '4.0') { - return projectGraphCompat5to4(projectGraph); + return projectGraphCompat5to4(projectGraph as ProjectGraph); } throw new Error( `Invalid source or target versions. Source: ${sourceVersion}, Target: ${targetVersion}. @@ -183,7 +171,7 @@ Check the versions running "nx report" and/or remove your "nxdeps.json" file (in * @param {ProjectGraph} projectGraph * @returns {ProjectGraph} */ -function projectGraphCompat5to4(projectGraph: ProjectGraph): ProjectGraph { +function projectGraphCompat5to4(projectGraph: ProjectGraph): ProjectGraphV4 { const { externalNodes, ...rest } = projectGraph; return { ...rest, diff --git a/packages/workspace/src/core/target-project-locator.ts b/packages/workspace/src/core/target-project-locator.ts index c8640fdcfc..dd1a29421b 100644 --- a/packages/workspace/src/core/target-project-locator.ts +++ b/packages/workspace/src/core/target-project-locator.ts @@ -1,7 +1,10 @@ import { resolveModuleByImport } from '../utilities/typescript'; import { readFileIfExisting } from './file-utils'; -import type { ProjectGraphNode } from '@nrwl/devkit'; -import { parseJson, ProjectGraphExternalNode } from '@nrwl/devkit'; +import { + parseJson, + ProjectGraphExternalNode, + ProjectGraphProjectNode, +} from '@nrwl/devkit'; import { isRelativePath } from '../utilities/fileutils'; import { dirname, join, posix } from 'path'; import { appRootPath } from '@nrwl/tao/src/utils/app-root'; @@ -17,7 +20,7 @@ export class TargetProjectLocator { private npmResolutionCache = new Map(); constructor( - private readonly nodes: Record, + private readonly nodes: Record, private readonly externalNodes: Record ) {} @@ -194,7 +197,9 @@ export class TargetProjectLocator { } } -function createProjectRootMappings(nodes: Record) { +function createProjectRootMappings( + nodes: Record +) { const projectRootMappings = new Map(); for (const projectName of Object.keys(nodes)) { const root = nodes[projectName].data.root; diff --git a/packages/workspace/src/tasks-runner/run-command.ts b/packages/workspace/src/tasks-runner/run-command.ts index e13c799cb5..81d1ede398 100644 --- a/packages/workspace/src/tasks-runner/run-command.ts +++ b/packages/workspace/src/tasks-runner/run-command.ts @@ -4,7 +4,7 @@ import { appRootPath } from '@nrwl/tao/src/utils/app-root'; import type { NxJsonConfiguration, ProjectGraph, - ProjectGraphNode, + ProjectGraphProjectNode, TargetDependencyConfig, Task, } from '@nrwl/devkit'; @@ -91,7 +91,7 @@ async function getTerminalOutputLifeCycle( } export async function runCommand( - projectsToRun: ProjectGraphNode[], + projectsToRun: ProjectGraphProjectNode[], projectGraph: ProjectGraph, { nxJson }: Environment, nxArgs: NxArgs, @@ -203,7 +203,7 @@ async function anyFailuresInObservable(obs: any) { } interface TaskParams { - project: ProjectGraphNode; + project: ProjectGraphProjectNode; target: string; configuration: string; overrides: Object; @@ -211,7 +211,7 @@ interface TaskParams { } export function createTasksForProjectToRun( - projectsToRun: ProjectGraphNode[], + projectsToRun: ProjectGraphProjectNode[], params: Omit, projectGraph: ProjectGraph, initiatingProject: string | null, @@ -345,7 +345,7 @@ export function createTask({ } function addTasksForProjectDependencyConfig( - project: ProjectGraphNode, + project: ProjectGraphProjectNode, { target, configuration, @@ -382,10 +382,13 @@ function addTasksForProjectDependencyConfig( const dependencies = projectGraph.dependencies[project.name]; if (dependencies) { for (const dep of dependencies) { - const depProject = - projectGraph.nodes[dep.target] || - projectGraph.externalNodes[dep.target]; - if (projectHasTarget(depProject, dependencyConfig.target)) { + const depProject = projectGraph.nodes[ + dep.target + ] as ProjectGraphProjectNode; + if ( + depProject && + projectHasTarget(depProject, dependencyConfig.target) + ) { addTasksForProjectTarget( { project: depProject, @@ -405,7 +408,10 @@ function addTasksForProjectDependencyConfig( if (seenSet.has(dep.target)) { continue; } - + if (!depProject) { + seenSet.add(dep.target); + continue; + } addTasksForProjectDependencyConfig( depProject, { target, configuration, overrides }, diff --git a/packages/workspace/src/tasks-runner/utils.ts b/packages/workspace/src/tasks-runner/utils.ts index f6b387b88e..763e050ebd 100644 --- a/packages/workspace/src/tasks-runner/utils.ts +++ b/packages/workspace/src/tasks-runner/utils.ts @@ -1,7 +1,7 @@ import { getPackageManagerCommand, ProjectGraph, - ProjectGraphNode, + ProjectGraphProjectNode, TargetDependencyConfig, Task, TaskGraph, @@ -51,13 +51,16 @@ export function getDependencyConfigs( return dependencyConfigs; } -export function getOutputs(p: Record, task: Task) { +export function getOutputs( + p: Record, + task: Task +) { return getOutputsForTargetAndConfiguration(task, p[task.target.project]); } export function getOutputsForTargetAndConfiguration( task: Pick, - node: ProjectGraphNode + node: ProjectGraphProjectNode ) { const { target, configuration } = task.target; diff --git a/packages/workspace/src/utilities/buildable-libs-utils.ts b/packages/workspace/src/utilities/buildable-libs-utils.ts index 6e798d56aa..407da3d47f 100644 --- a/packages/workspace/src/utilities/buildable-libs-utils.ts +++ b/packages/workspace/src/utilities/buildable-libs-utils.ts @@ -1,14 +1,19 @@ import { isNpmProject, ProjectType } from '../core/project-graph'; import { join, resolve, dirname, relative } from 'path'; import { directoryExists } from './fileutils'; -import { stripIndents, readJsonFile, writeJsonFile } from '@nrwl/devkit'; -import type { ProjectGraph, ProjectGraphNode } from '@nrwl/devkit'; +import { + stripIndents, + readJsonFile, + writeJsonFile, + ProjectGraphExternalNode, +} from '@nrwl/devkit'; +import type { ProjectGraph, ProjectGraphProjectNode } from '@nrwl/devkit'; import { getOutputsForTargetAndConfiguration } from '../tasks-runner/utils'; import * as ts from 'typescript'; import { unlinkSync } from 'fs'; import { output } from './output'; -function isBuildable(target: string, node: ProjectGraphNode): boolean { +function isBuildable(target: string, node: ProjectGraphProjectNode): boolean { return ( node.data.targets && node.data.targets[target] && @@ -19,7 +24,7 @@ function isBuildable(target: string, node: ProjectGraphNode): boolean { export type DependentBuildableProjectNode = { name: string; outputs: string[]; - node: ProjectGraphNode; + node: ProjectGraphProjectNode | ProjectGraphExternalNode; }; export function calculateProjectDependencies( @@ -29,7 +34,7 @@ export function calculateProjectDependencies( targetName: string, configurationName: string ): { - target: ProjectGraphNode; + target: ProjectGraphProjectNode; dependencies: DependentBuildableProjectNode[]; nonBuildableDependencies: string[]; } { @@ -255,7 +260,7 @@ export function updateBuildableProjectPackageJsonDependencies( projectName: string, targetName: string, configurationName: string, - node: ProjectGraphNode, + node: ProjectGraphProjectNode, dependencies: DependentBuildableProjectNode[], typeOfDependency: 'dependencies' | 'peerDependencies' = 'dependencies' ) { diff --git a/packages/workspace/src/utilities/project-graph-utils.ts b/packages/workspace/src/utilities/project-graph-utils.ts index c79566560b..790e5e2e84 100644 --- a/packages/workspace/src/utilities/project-graph-utils.ts +++ b/packages/workspace/src/utilities/project-graph-utils.ts @@ -1,8 +1,7 @@ import { normalizePath, - NxPlugin, ProjectGraph, - ProjectGraphNode, + ProjectGraphProjectNode, readJsonFile, TargetConfiguration, } from '@nrwl/devkit'; @@ -10,16 +9,18 @@ import { buildTargetFromScript, PackageJson, } from '@nrwl/tao/src/shared/package-json'; -import { sync } from 'glob'; import { join, relative } from 'path'; import { readCachedProjectGraph } from '../core/project-graph'; -export function projectHasTarget(project: ProjectGraphNode, target: string) { +export function projectHasTarget( + project: ProjectGraphProjectNode, + target: string +) { return project.data && project.data.targets && project.data.targets[target]; } export function projectHasTargetAndConfiguration( - project: ProjectGraphNode, + project: ProjectGraphProjectNode, target: string, configuration: string ) { @@ -111,7 +112,7 @@ function findAllProjectNodeDependencies( const dependencyNodeNames = new Set(); collectDependentProjectNodesNames( - projectGraph, + projectGraph as ProjectGraph, dependencyNodeNames, parentNodeName ); diff --git a/packages/workspace/src/utils/graph-utils.ts b/packages/workspace/src/utils/graph-utils.ts index 2846d32688..95a5542cae 100644 --- a/packages/workspace/src/utils/graph-utils.ts +++ b/packages/workspace/src/utils/graph-utils.ts @@ -1,5 +1,8 @@ -import type { FileData, ProjectGraph, ProjectGraphNode } from '@nrwl/devkit'; -import { isWorkspaceProject } from '../core/project-graph/operators'; +import type { + FileData, + ProjectGraph, + ProjectGraphProjectNode, +} from '@nrwl/devkit'; interface Reach { graph: ProjectGraph; @@ -63,7 +66,7 @@ export function getPath( graph: ProjectGraph, sourceProjectName: string, targetProjectName: string -): Array { +): Array { if (sourceProjectName === targetProjectName) return []; if (reach.graph !== graph) { @@ -105,16 +108,16 @@ export function getPath( export function checkCircularPath( graph: ProjectGraph, - sourceProject: ProjectGraphNode, - targetProject: ProjectGraphNode -): Array { + sourceProject: ProjectGraphProjectNode, + targetProject: ProjectGraphProjectNode +): Array { if (!graph.nodes[targetProject.name]) return []; return getPath(graph, targetProject.name, sourceProject.name); } export function findFilesInCircularPath( - circularPath: ProjectGraphNode[] + circularPath: ProjectGraphProjectNode[] ): Array { const filePathChain = []; diff --git a/packages/workspace/src/utils/runtime-lint-utils.ts b/packages/workspace/src/utils/runtime-lint-utils.ts index 212a161b95..67cab6628f 100644 --- a/packages/workspace/src/utils/runtime-lint-utils.ts +++ b/packages/workspace/src/utils/runtime-lint-utils.ts @@ -3,7 +3,6 @@ import { FileData, readFileIfExisting } from '../core/file-utils'; import { ProjectGraph, ProjectGraphDependency, - ProjectGraphNode, ProjectGraphProjectNode, normalizePath, DependencyType, @@ -31,13 +30,13 @@ export type DepConstraint = { }; export function hasNoneOfTheseTags( - proj: ProjectGraphNode, + proj: ProjectGraphProjectNode, tags: string[] ) { return tags.filter((allowedTag) => hasTag(proj, allowedTag)).length === 0; } -function hasTag(proj: ProjectGraphNode, tag: string) { +function hasTag(proj: ProjectGraphProjectNode, tag: string) { return tag === '*' || (proj.data.tags || []).indexOf(tag) > -1; } @@ -76,7 +75,7 @@ export function isRelativeImportIntoAnotherProject( projectPath: string, projectGraph: MappedProjectGraph, sourceFilePath: string, - sourceProject: ProjectGraphNode + sourceProject: ProjectGraphProjectNode ): boolean { if (!isRelative(imp)) return false; @@ -152,7 +151,7 @@ export function findProjectUsingImport( export function findConstraintsFor( depConstraints: DepConstraint[], - sourceProject: ProjectGraphNode + sourceProject: ProjectGraphProjectNode ) { return depConstraints.filter((f) => hasTag(sourceProject, f.sourceTag)); } @@ -181,8 +180,8 @@ export function getSourceFilePath(sourceFileName: string, projectPath: string) { } export function hasBannedImport( - source: ProjectGraphNode, - target: ProjectGraphNode, + source: ProjectGraphProjectNode, + target: ProjectGraphProjectNode | ProjectGraphExternalNode, depConstraints: DepConstraint[] ): DepConstraint | null { // return those constraints that match source projec and have `bannedExternalImports` defined @@ -234,7 +233,9 @@ function parseImportWildcards(importDefinition: string): RegExp { * Verifies whether the given node has an architect builder attached * @param projectGraph the node to verify */ -export function hasBuildExecutor(projectGraph: ProjectGraphNode): boolean { +export function hasBuildExecutor( + projectGraph: ProjectGraphProjectNode +): boolean { return ( // can the architect not be defined? real use case? projectGraph.data.targets &&