feat(core): use stricter types for project graph node references (#8813)

This commit is contained in:
Miroslav Jonaš 2022-02-16 11:45:04 +01:00 committed by GitHub
parent 96be786dcc
commit b251234af9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 216 additions and 156 deletions

View File

@ -1,9 +1,12 @@
// nx-ignore-next-line // 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 { depGraphMachine } from './dep-graph.machine';
import { interpret } from 'xstate'; import { interpret } from 'xstate';
export const mockProjects: ProjectGraphNode[] = [ export const mockProjects: ProjectGraphProjectNode[] = [
{ {
name: 'app1', name: 'app1',
type: 'app', type: 'app',

View File

@ -1,5 +1,8 @@
// nx-ignore-next-line // 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 type { VirtualElement } from '@popperjs/core';
import { default as cy } from 'cytoscape'; import { default as cy } from 'cytoscape';
import { default as cytoscapeDagre } from 'cytoscape-dagre'; import { default as cytoscapeDagre } from 'cytoscape-dagre';
@ -323,7 +326,7 @@ export class GraphService {
} }
initGraph( initGraph(
allProjects: ProjectGraphNode[], allProjects: ProjectGraphProjectNode[],
groupByFolder: boolean, groupByFolder: boolean,
workspaceLayout, workspaceLayout,
dependencies: Record<string, ProjectGraphDependency[]>, dependencies: Record<string, ProjectGraphDependency[]>,
@ -341,7 +344,7 @@ export class GraphService {
} }
private generateCytoscapeLayout( private generateCytoscapeLayout(
allProjects: ProjectGraphNode[], allProjects: ProjectGraphProjectNode[],
groupByFolder: boolean, groupByFolder: boolean,
workspaceLayout, workspaceLayout,
dependencies: Record<string, ProjectGraphDependency[]>, dependencies: Record<string, ProjectGraphDependency[]>,
@ -364,7 +367,7 @@ export class GraphService {
} }
private createElements( private createElements(
projects: ProjectGraphNode[], projects: ProjectGraphProjectNode[],
groupByFolder: boolean, groupByFolder: boolean,
workspaceLayout: { workspaceLayout: {
appsDir: string; appsDir: string;

View File

@ -1,5 +1,8 @@
// nx-ignore-next-line // 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'; import { ActionObject, ActorRef, State, StateNodeConfig } from 'xstate';
// The hierarchical (recursive) schema for the states // The hierarchical (recursive) schema for the states
@ -43,7 +46,7 @@ export type DepGraphUIEvents =
| { type: 'clearTextFilter' } | { type: 'clearTextFilter' }
| { | {
type: 'initGraph'; type: 'initGraph';
projects: ProjectGraphNode[]; projects: ProjectGraphProjectNode[];
dependencies: Record<string, ProjectGraphDependency[]>; dependencies: Record<string, ProjectGraphDependency[]>;
affectedProjects: string[]; affectedProjects: string[];
workspaceLayout: { workspaceLayout: {
@ -53,7 +56,7 @@ export type DepGraphUIEvents =
} }
| { | {
type: 'updateGraph'; type: 'updateGraph';
projects: ProjectGraphNode[]; projects: ProjectGraphProjectNode[];
dependencies: Record<string, ProjectGraphDependency[]>; dependencies: Record<string, ProjectGraphDependency[]>;
}; };
@ -62,7 +65,7 @@ export type DepGraphUIEvents =
export type GraphRenderEvents = export type GraphRenderEvents =
| { | {
type: 'notifyGraphInitGraph'; type: 'notifyGraphInitGraph';
projects: ProjectGraphNode[]; projects: ProjectGraphProjectNode[];
dependencies: Record<string, ProjectGraphDependency[]>; dependencies: Record<string, ProjectGraphDependency[]>;
affectedProjects: string[]; affectedProjects: string[];
workspaceLayout: { workspaceLayout: {
@ -73,7 +76,7 @@ export type GraphRenderEvents =
} }
| { | {
type: 'notifyGraphUpdateGraph'; type: 'notifyGraphUpdateGraph';
projects: ProjectGraphNode[]; projects: ProjectGraphProjectNode[];
dependencies: Record<string, ProjectGraphDependency[]>; dependencies: Record<string, ProjectGraphDependency[]>;
affectedProjects: string[]; affectedProjects: string[];
workspaceLayout: { workspaceLayout: {
@ -141,7 +144,7 @@ export type AllEvents = DepGraphUIEvents | GraphRenderEvents | RouteEvents;
// The context (extended state) of the machine // The context (extended state) of the machine
export interface DepGraphContext { export interface DepGraphContext {
projects: ProjectGraphNode[]; projects: ProjectGraphProjectNode[];
dependencies: Record<string, ProjectGraphDependency[]>; dependencies: Record<string, ProjectGraphDependency[]>;
affectedProjects: string[]; affectedProjects: string[];
selectedProjects: string[]; selectedProjects: string[];

View File

@ -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 { DepGraphSelector } from '../hooks/use-dep-graph-selector';
import { WorkspaceLayout } from '../interfaces'; import { WorkspaceLayout } from '../interfaces';
import { GraphPerfReport } from './interfaces'; import { GraphPerfReport } from './interfaces';
export const allProjectsSelector: DepGraphSelector<ProjectGraphNode[]> = ( export const allProjectsSelector: DepGraphSelector<
state ProjectGraphProjectNode[]
) => state.context.projects; > = (state) => state.context.projects;
export const workspaceLayoutSelector: DepGraphSelector<WorkspaceLayout> = ( export const workspaceLayoutSelector: DepGraphSelector<WorkspaceLayout> = (
state state

View File

@ -1,4 +1,7 @@
import type { ProjectGraphDependency, ProjectGraphNode } from '@nrwl/devkit'; import type {
ProjectGraphDependency,
ProjectGraphProjectNode,
} from '@nrwl/devkit';
// nx-ignore-next-line // nx-ignore-next-line
import type { DepGraphClientResponse } from '@nrwl/workspace/src/command-line/dep-graph'; import type { DepGraphClientResponse } from '@nrwl/workspace/src/command-line/dep-graph';
import { ProjectGraphService } from '../app/interfaces'; import { ProjectGraphService } from '../app/interfaces';
@ -56,7 +59,7 @@ export class MockProjectGraphService implements ProjectGraphService {
return new Promise((resolve) => resolve(this.response)); return new Promise((resolve) => resolve(this.response));
} }
private createNewProject(): ProjectGraphNode { private createNewProject(): ProjectGraphProjectNode {
const type = Math.random() > 0.25 ? 'lib' : 'app'; const type = Math.random() > 0.25 ? 'lib' : 'app';
const name = `${type}-${this.response.projects.length + 1}`; const name = `${type}-${this.response.projects.length + 1}`;

View File

@ -1,4 +1,4 @@
import type { ProjectGraphNode } from '@nrwl/devkit'; import type { ProjectGraphProjectNode } from '@nrwl/devkit';
import * as cy from 'cytoscape'; import * as cy from 'cytoscape';
import { parseParentDirectoriesFromPilePath } from '../util'; import { parseParentDirectoriesFromPilePath } from '../util';
@ -18,7 +18,7 @@ export class ProjectNode {
focused = false; focused = false;
constructor( constructor(
private project: ProjectGraphNode, private project: ProjectGraphProjectNode,
private workspaceRoot: string private workspaceRoot: string
) {} ) {}

View File

@ -40,6 +40,7 @@ It only uses language primitives and immutable objects
- [ProjectGraphExternalNode](../../nx-devkit/index#projectgraphexternalnode) - [ProjectGraphExternalNode](../../nx-devkit/index#projectgraphexternalnode)
- [ProjectGraphProcessorContext](../../nx-devkit/index#projectgraphprocessorcontext) - [ProjectGraphProcessorContext](../../nx-devkit/index#projectgraphprocessorcontext)
- [ProjectGraphProjectNode](../../nx-devkit/index#projectgraphprojectnode) - [ProjectGraphProjectNode](../../nx-devkit/index#projectgraphprojectnode)
- [ProjectGraphV4](../../nx-devkit/index#projectgraphv4)
### Tree Interfaces ### Tree Interfaces
@ -240,6 +241,18 @@ A plugin for Nx
--- ---
### ProjectGraphV4
**ProjectGraphV4**<`T`\>: `Object`
#### Type parameters
| Name | Type |
| :--- | :---- |
| `T` | `any` |
---
## Tree Interfaces ## Tree Interfaces
### FileChange ### FileChange

View File

@ -144,6 +144,7 @@ export type {
ProjectFileMap, ProjectFileMap,
FileData, FileData,
ProjectGraph, ProjectGraph,
ProjectGraphV4,
ProjectGraphDependency, ProjectGraphDependency,
ProjectGraphNode, ProjectGraphNode,
ProjectGraphProjectNode, ProjectGraphProjectNode,

View File

@ -2,7 +2,7 @@ import type {
ProjectGraph, ProjectGraph,
ProjectGraphDependency, ProjectGraphDependency,
ProjectGraphExternalNode, ProjectGraphExternalNode,
ProjectGraphNode, ProjectGraphProjectNode,
} from './interfaces'; } from './interfaces';
import { DependencyType } from './interfaces'; import { DependencyType } from './interfaces';
@ -28,7 +28,7 @@ export class ProjectGraphBuilder {
/** /**
* Adds a project node to the project graph * 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 // Check if project with the same name already exists
if (this.graph.nodes[node.name]) { if (this.graph.nodes[node.name]) {
// Throw if existing project is of a different type // Throw if existing project is of a different type

View File

@ -25,7 +25,7 @@ export interface ProjectFileMap {
* A Graph of projects in the workspace and dependencies between them * A Graph of projects in the workspace and dependencies between them
*/ */
export interface ProjectGraph<T = any> { export interface ProjectGraph<T = any> {
nodes: Record<string, ProjectGraphNode<T>>; nodes: Record<string, ProjectGraphProjectNode<T>>;
externalNodes?: Record<string, ProjectGraphExternalNode>; externalNodes?: Record<string, ProjectGraphExternalNode>;
dependencies: Record<string, ProjectGraphDependency[]>; dependencies: Record<string, ProjectGraphDependency[]>;
// this is optional otherwise it might break folks who use project graph creation // this is optional otherwise it might break folks who use project graph creation
@ -33,6 +33,14 @@ export interface ProjectGraph<T = any> {
version?: string; version?: string;
} }
export interface ProjectGraphV4<T = any> {
nodes: Record<string, ProjectGraphNode<T>>;
dependencies: Record<string, ProjectGraphDependency[]>;
// this is optional otherwise it might break folks who use project graph creation
allWorkspaceFiles?: FileData[];
version?: string;
}
/** /**
* Type of dependency between projects * 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<T = any> = export type ProjectGraphNode<T = any> =
| ProjectGraphProjectNode<T> | ProjectGraphProjectNode<T>

View File

@ -6,8 +6,11 @@ import { from, Observable, of } from 'rxjs';
import { catchError, concatMap, last, scan, tap } from 'rxjs/operators'; import { catchError, concatMap, last, scan, tap } from 'rxjs/operators';
import { eachValueFrom } from 'rxjs-for-await'; import { eachValueFrom } from 'rxjs-for-await';
import * as autoprefixer from 'autoprefixer'; import * as autoprefixer from 'autoprefixer';
import type {
import type { ExecutorContext, ProjectGraphNode } from '@nrwl/devkit'; ExecutorContext,
ProjectGraphExternalNode,
ProjectGraphProjectNode,
} from '@nrwl/devkit';
import { logger, names, readJsonFile, writeJsonFile } from '@nrwl/devkit'; import { logger, names, readJsonFile, writeJsonFile } from '@nrwl/devkit';
import { readCachedProjectGraph } from '@nrwl/workspace/src/core/project-graph'; import { readCachedProjectGraph } from '@nrwl/workspace/src/core/project-graph';
import { import {
@ -320,7 +323,7 @@ function createCompilerOptions(format, options, dependencies) {
function updatePackageJson( function updatePackageJson(
options: NormalizedWebRollupOptions, options: NormalizedWebRollupOptions,
context: ExecutorContext, context: ExecutorContext,
target: ProjectGraphNode, target: ProjectGraphProjectNode,
dependencies: DependentBuildableProjectNode[], dependencies: DependentBuildableProjectNode[],
packageJson: any packageJson: any
) { ) {

View File

@ -3,14 +3,11 @@ import { filterAffected } from '../core/affected-project-graph';
import { calculateFileChanges, readEnvironment } from '../core/file-utils'; import { calculateFileChanges, readEnvironment } from '../core/file-utils';
import { import {
createProjectGraphAsync, createProjectGraphAsync,
ProjectGraphNodeRecords,
ProjectType, ProjectType,
withDeps, withDeps,
} from '../core/project-graph'; } from '../core/project-graph';
import { import { ProjectGraph, ProjectGraphProjectNode } from '@nrwl/devkit';
ProjectGraph,
ProjectGraphNode,
ProjectGraphProjectNode,
} from '@nrwl/devkit';
import { runCommand } from '../tasks-runner/run-command'; import { runCommand } from '../tasks-runner/run-command';
import { output } from '../utilities/output'; import { output } from '../utilities/output';
import { projectHasTarget } from '../utilities/project-graph-utils'; 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 let affectedGraph = nxArgs.all
? projectGraph ? projectGraph
: filterAffected( : filterAffected(
@ -143,15 +143,18 @@ function projectsToRun(nxArgs: NxArgs, projectGraph: ProjectGraph) {
if (nxArgs.exclude) { if (nxArgs.exclude) {
const excludedProjects = new Set(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)) .filter(([projectName]) => !excludedProjects.has(projectName))
.map(([, project]) => project); .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)); return projects.filter((p) => projectHasTarget(p, nxArgs.target));
} }

View File

@ -8,7 +8,7 @@ import * as http from 'http';
import ignore from 'ignore'; import ignore from 'ignore';
import * as open from 'open'; import * as open from 'open';
import { basename, dirname, extname, isAbsolute, join, parse } from 'path'; 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 { performance } from 'perf_hooks';
import { URL, URLSearchParams } from 'url'; import { URL, URLSearchParams } from 'url';
import { workspaceLayout } from '../core/file-utils'; import { workspaceLayout } from '../core/file-utils';
@ -17,14 +17,14 @@ import {
createProjectGraphAsync, createProjectGraphAsync,
ProjectGraph, ProjectGraph,
ProjectGraphDependency, ProjectGraphDependency,
ProjectGraphNode, ProjectGraphProjectNode,
pruneExternalNodes, pruneExternalNodes,
} from '../core/project-graph'; } from '../core/project-graph';
import { output } from '../utilities/output'; import { output } from '../utilities/output';
export interface DepGraphClientResponse { export interface DepGraphClientResponse {
hash: string; hash: string;
projects: ProjectGraphNode[]; projects: ProjectGraphProjectNode[];
dependencies: Record<string, ProjectGraphDependency[]>; dependencies: Record<string, ProjectGraphDependency[]>;
layout: { appsDir: string; libsDir: string }; layout: { appsDir: string; libsDir: string };
affected: string[]; affected: string[];
@ -86,7 +86,10 @@ function buildEnvironmentJs(
return environmentJs; return environmentJs;
} }
function projectExists(projects: ProjectGraphNode[], projectToFind: string) { function projectExists(
projects: ProjectGraphProjectNode[],
projectToFind: string
) {
return ( return (
projects.find((project) => project.name === projectToFind) !== undefined projects.find((project) => project.name === projectToFind) !== undefined
); );
@ -113,9 +116,9 @@ function filterGraph(
focus: string, focus: string,
exclude: string[] exclude: string[]
): ProjectGraph { ): ProjectGraph {
let projectNames = (Object.values(graph.nodes) as ProjectGraphNode[]).map( let projectNames = (
(project) => project.name Object.values(graph.nodes) as ProjectGraphProjectNode[]
); ).map((project) => project.name);
let filteredProjectNames: Set<string>; let filteredProjectNames: Set<string>;
@ -166,7 +169,7 @@ export async function generateGraph(
let graph = pruneExternalNodes(await createProjectGraphAsync()); let graph = pruneExternalNodes(await createProjectGraphAsync());
const layout = workspaceLayout(); const layout = workspaceLayout();
const projects = Object.values(graph.nodes) as ProjectGraphNode[]; const projects = Object.values(graph.nodes) as ProjectGraphProjectNode[];
projects.sort((a, b) => { projects.sort((a, b) => {
return a.name.localeCompare(b.name); return a.name.localeCompare(b.name);
}); });

View File

@ -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 type { Environment } from '../core/shared-interfaces';
import { createTask } from '../tasks-runner/run-command'; import { createTask } from '../tasks-runner/run-command';
import { getCommandAsString, getOutputs } from '../tasks-runner/utils'; import { getCommandAsString, getOutputs } from '../tasks-runner/utils';
@ -6,8 +6,8 @@ import * as yargs from 'yargs';
import type { NxArgs } from './utils'; import type { NxArgs } from './utils';
export async function printAffected( export async function printAffected(
affectedProjectsWithTargetAndConfig: ProjectGraphNode[], affectedProjectsWithTargetAndConfig: ProjectGraphProjectNode[],
affectedProjects: ProjectGraphNode[], affectedProjects: ProjectGraphProjectNode[],
projectGraph: ProjectGraph, projectGraph: ProjectGraph,
{ nxJson }: Environment, { nxJson }: Environment,
nxArgs: NxArgs, nxArgs: NxArgs,
@ -33,7 +33,7 @@ export async function printAffected(
} }
async function createTasks( async function createTasks(
affectedProjectsWithTargetAndConfig: ProjectGraphNode[], affectedProjectsWithTargetAndConfig: ProjectGraphProjectNode[],
projectGraph: ProjectGraph, projectGraph: ProjectGraph,
nxArgs: NxArgs, nxArgs: NxArgs,
overrides: yargs.Arguments overrides: yargs.Arguments

View File

@ -3,7 +3,7 @@ import { runCommand } from '../tasks-runner/run-command';
import type { NxArgs, RawNxArgs } from './utils'; import type { NxArgs, RawNxArgs } from './utils';
import { splitArgsIntoNxArgsAndOverrides } from './utils'; import { splitArgsIntoNxArgsAndOverrides } from './utils';
import { createProjectGraphAsync } from '../core/project-graph'; 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 { readEnvironment } from '../core/file-utils';
import { projectHasTarget } from '../utilities/project-graph-utils'; import { projectHasTarget } from '../utilities/project-graph-utils';
import { output } from '../utilities/output'; import { output } from '../utilities/output';
@ -37,7 +37,7 @@ export async function runMany(parsedArgs: yargs.Arguments & RawNxArgs) {
function projectsToRun( function projectsToRun(
nxArgs: NxArgs, nxArgs: NxArgs,
projectGraph: ProjectGraph projectGraph: ProjectGraph
): ProjectGraphNode[] { ): ProjectGraphProjectNode[] {
const allProjects = Object.values(projectGraph.nodes); const allProjects = Object.values(projectGraph.nodes);
const excludedProjects = new Set(nxArgs.exclude ?? []); const excludedProjects = new Set(nxArgs.exclude ?? []);
if (nxArgs.all) { if (nxArgs.all) {
@ -56,7 +56,7 @@ function projectsToRun(
function checkForInvalidProjects( function checkForInvalidProjects(
nxArgs: NxArgs, nxArgs: NxArgs,
allProjects: ProjectGraphNode[] allProjects: ProjectGraphProjectNode[]
) { ) {
const invalid = nxArgs.projects.filter( const invalid = nxArgs.projects.filter(
(name) => !allProjects.find((p) => p.name === name) (name) => !allProjects.find((p) => p.name === name)
@ -67,12 +67,12 @@ function checkForInvalidProjects(
} }
function runnableForTarget( function runnableForTarget(
projects: ProjectGraphNode[], projects: ProjectGraphProjectNode[],
target: string, target: string,
strict = false strict = false
): ProjectGraphNode[] { ): ProjectGraphProjectNode[] {
const notRunnable = [] as ProjectGraphNode[]; const notRunnable = [] as ProjectGraphProjectNode[];
const runnable = [] as ProjectGraphNode[]; const runnable = [] as ProjectGraphProjectNode[];
for (let project of projects) { for (let project of projects) {
if (projectHasTarget(project, target)) { if (projectHasTarget(project, target)) {

View File

@ -5,7 +5,7 @@ import {
JsonChange, JsonChange,
} from '../../../utilities/json-diff'; } from '../../../utilities/json-diff';
import { TouchedProjectLocator } from '../affected-project-graph-models'; import { TouchedProjectLocator } from '../affected-project-graph-models';
import { ProjectGraphNode } from '../../project-graph'; import { ProjectGraphProjectNode } from '../../project-graph';
export const getTouchedProjectsFromTsConfig: TouchedProjectLocator< export const getTouchedProjectsFromTsConfig: TouchedProjectLocator<
WholeFileChange | JsonChange WholeFileChange | JsonChange
@ -54,7 +54,7 @@ function allChangesArePathChanges(
*/ */
function getProjectsAffectedByPaths( function getProjectsAffectedByPaths(
change: JsonChange, change: JsonChange,
nodes: ProjectGraphNode[] nodes: ProjectGraphProjectNode[]
) { ) {
const result = []; const result = [];
const paths: string[] = [change.value.lhs, change.value.rhs]; const paths: string[] = [change.value.lhs, change.value.rhs];

View File

@ -3,11 +3,7 @@ import {
WorkspaceJsonConfiguration, WorkspaceJsonConfiguration,
Workspaces, Workspaces,
} from '@nrwl/tao/src/shared/workspace'; } from '@nrwl/tao/src/shared/workspace';
import type { import type { FileData, NxJsonConfiguration } from '@nrwl/devkit';
FileData,
NxJsonConfiguration,
ProjectGraphNode,
} from '@nrwl/devkit';
import { readJsonFile } from '@nrwl/devkit'; import { readJsonFile } from '@nrwl/devkit';
import { execSync } from 'child_process'; import { execSync } from 'child_process';
import { existsSync, readFileSync } from 'fs'; import { existsSync, readFileSync } from 'fs';

View File

@ -1,4 +1,8 @@
import { NxJsonConfiguration, WorkspaceJsonConfiguration } from '@nrwl/devkit'; import {
NxJsonConfiguration,
ProjectGraph,
WorkspaceJsonConfiguration,
} from '@nrwl/devkit';
import { import {
createCache as _createCache, createCache as _createCache,
extractCachedFileData, extractCachedFileData,
@ -284,7 +288,7 @@ describe('nx deps utils', () => {
_createCache( _createCache(
createNxJson({}), createNxJson({}),
createPackageJsonDeps({}), createPackageJsonDeps({}),
createCache({}), createCache({}) as ProjectGraph,
{} {}
); );
}); });
@ -293,7 +297,7 @@ describe('nx deps utils', () => {
const result = _createCache( const result = _createCache(
createNxJson({}), createNxJson({}),
createPackageJsonDeps({}), createPackageJsonDeps({}),
createCache({}), createCache({}) as ProjectGraph,
undefined undefined
); );
@ -303,7 +307,7 @@ describe('nx deps utils', () => {
function createCache(p: Partial<ProjectGraphCache>): ProjectGraphCache { function createCache(p: Partial<ProjectGraphCache>): ProjectGraphCache {
const defaults: ProjectGraphCache = { const defaults: ProjectGraphCache = {
version: '3.0', version: '5.0',
deps: { deps: {
'@nrwl/workspace': '12.0.0', '@nrwl/workspace': '12.0.0',
plugin: '1.0.0', plugin: '1.0.0',

View File

@ -77,7 +77,7 @@ export function readCache(): null | ProjectGraphCache {
export function createCache( export function createCache(
nxJson: NxJsonConfiguration<'*' | string[]>, nxJson: NxJsonConfiguration<'*' | string[]>,
packageJsonDeps: Record<string, string>, packageJsonDeps: Record<string, string>,
projectGraph: ProjectGraph<any>, projectGraph: ProjectGraph,
tsConfig: { compilerOptions?: { paths?: { [p: string]: any } } } tsConfig: { compilerOptions?: { paths?: { [p: string]: any } } }
) { ) {
const nxJsonPlugins = (nxJson.plugins || []).map((p) => ({ const nxJsonPlugins = (nxJson.plugins || []).map((p) => ({

View File

@ -1,6 +1,6 @@
import { buildExplicitPackageJsonDependencies } from './explicit-package-json-dependencies'; import { buildExplicitPackageJsonDependencies } from './explicit-package-json-dependencies';
import { vol } from 'memfs'; import { vol } from 'memfs';
import { ProjectGraphNode } from '../project-graph-models'; import { ProjectGraphProjectNode } from '../project-graph-models';
import { import {
ProjectGraphBuilder, ProjectGraphBuilder,
ProjectGraphProcessorContext, ProjectGraphProcessorContext,
@ -15,7 +15,7 @@ jest.mock('@nrwl/tao/src/utils/app-root', () => ({
describe('explicit package json dependencies', () => { describe('explicit package json dependencies', () => {
let ctx: ProjectGraphProcessorContext; let ctx: ProjectGraphProcessorContext;
let projects: Record<string, ProjectGraphNode>; let projects: Record<string, ProjectGraphProjectNode>;
let fsJson; let fsJson;
beforeEach(() => { beforeEach(() => {
const workspaceJson = { const workspaceJson = {

View File

@ -17,7 +17,12 @@ export function buildExplicitPackageJsonDependencies(
let packageNameMap = undefined; let packageNameMap = undefined;
Object.keys(filesToProcess).forEach((source) => { Object.keys(filesToProcess).forEach((source) => {
Object.values(filesToProcess[source]).forEach((f) => { 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 // we only create the package name map once and only if a package.json file changes
packageNameMap = packageNameMap || createPackageNameMap(workspace); packageNameMap = packageNameMap || createPackageNameMap(workspace);
processPackageJson(source, f.file, graph, res, packageNameMap); processPackageJson(source, f.file, graph, res, packageNameMap);

View File

@ -6,7 +6,7 @@ jest.mock('@nrwl/tao/src/utils/app-root', () => ({
})); }));
import { vol } from 'memfs'; import { vol } from 'memfs';
import { ProjectGraphNode } from '../project-graph-models'; import { ProjectGraphProjectNode } from '../project-graph-models';
import { buildExplicitTypeScriptDependencies } from './explicit-project-dependencies'; import { buildExplicitTypeScriptDependencies } from './explicit-project-dependencies';
import { import {
ProjectGraphBuilder, ProjectGraphBuilder,
@ -16,7 +16,7 @@ import { defaultFileHasher } from '../../hasher/file-hasher';
describe('explicit project dependencies', () => { describe('explicit project dependencies', () => {
let ctx: ProjectGraphProcessorContext; let ctx: ProjectGraphProcessorContext;
let projects: Record<string, ProjectGraphNode>; let projects: Record<string, ProjectGraphProjectNode>;
let fsJson; let fsJson;
beforeEach(() => { beforeEach(() => {
const workspaceJson = { const workspaceJson = {

View File

@ -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 { TypeScriptImportLocator } from './typescript-import-locator';
import { TargetProjectLocator } from '../../target-project-locator'; import { TargetProjectLocator } from '../../target-project-locator';
import { import { ProjectFileMap, Workspace } from '@nrwl/devkit';
ProjectFileMap,
ProjectGraphBuilder,
ProjectGraphProcessorContext,
Workspace,
} from '@nrwl/devkit';
export function buildExplicitTypeScriptDependencies( export function buildExplicitTypeScriptDependencies(
workspace: Workspace, workspace: Workspace,
@ -15,7 +14,7 @@ export function buildExplicitTypeScriptDependencies(
) { ) {
const importLocator = new TypeScriptImportLocator(); const importLocator = new TypeScriptImportLocator();
const targetProjectLocator = new TargetProjectLocator( const targetProjectLocator = new TargetProjectLocator(
graph.nodes, graph.nodes as ProjectGraphNodeRecords,
graph.externalNodes graph.externalNodes
); );
const res = [] as any; const res = [] as any;

View File

@ -3,7 +3,6 @@ import {
logger, logger,
NxJsonConfiguration, NxJsonConfiguration,
NxJsonProjectConfiguration, NxJsonProjectConfiguration,
NxPlugin,
ProjectConfiguration, ProjectConfiguration,
ProjectFileMap, ProjectFileMap,
ProjectGraph, ProjectGraph,

View File

@ -69,7 +69,9 @@ export function filterNodes(
/** /**
* @deprecated will be removed in v14. All projects in ProjectGraph's `nodes` are workspace projects * @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 ( return (
project.type === 'app' || project.type === 'lib' || project.type === 'e2e' project.type === 'app' || project.type === 'lib' || project.type === 'e2e'
); );

View File

@ -1,13 +1,13 @@
import type { DependencyType, ProjectGraphNode } from '@nrwl/devkit'; import type { ProjectGraphProjectNode } from '@nrwl/devkit';
export { export {
ProjectGraph, ProjectGraph,
ProjectGraphDependency, ProjectGraphDependency,
ProjectGraphNode, ProjectGraphProjectNode,
DependencyType, DependencyType,
} from '@nrwl/devkit'; } from '@nrwl/devkit';
export type ProjectGraphNodeRecords = Record<string, ProjectGraphNode>; export type ProjectGraphNodeRecords = Record<string, ProjectGraphProjectNode>;
export enum ProjectType { export enum ProjectType {
app = 'app', app = 'app',

View File

@ -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 { ProjectGraphCache, readCache } from '../nx-deps/nx-deps-cache';
import { buildProjectGraph } from './build-project-graph'; import { buildProjectGraph } from './build-project-graph';
import { readNxJson, workspaceFileName } from '../file-utils'; 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. * Synchronously reads the latest cached copy of the workspace's ProjectGraph.
* @throws {Error} if there is no cached ProjectGraph to read from * @throws {Error} if there is no cached ProjectGraph to read from
*/ */
export function readCachedProjectGraph( export function readCachedProjectGraph(): ProjectGraph {
projectGraphVersion = '5.0'
): ProjectGraph {
const projectGraphCache: ProjectGraphCache | false = readCache(); const projectGraphCache: ProjectGraphCache | false = readCache();
const angularSpecificError = const angularSpecificError =
workspaceFileName() === 'angular.json' workspaceFileName() === 'angular.json'
@ -45,32 +43,26 @@ export function readCachedProjectGraph(
nodes: projectGraphCache.nodes, nodes: projectGraphCache.nodes,
externalNodes: projectGraphCache.externalNodes, externalNodes: projectGraphCache.externalNodes,
dependencies: projectGraphCache.dependencies, dependencies: projectGraphCache.dependencies,
}; } as ProjectGraph;
return projectGraphAdapter( return projectGraphAdapter(
projectGraph.version, projectGraph.version,
projectGraphVersion, '5.0',
projectGraph projectGraph
); ) as ProjectGraph;
} }
async function buildProjectGraphWithoutDaemon(projectGraphVersion: string) { async function buildProjectGraphWithoutDaemon() {
try { try {
await defaultFileHasher.ensureInitialized(); await defaultFileHasher.ensureInitialized();
return projectGraphAdapter( return await buildProjectGraph();
'5.0',
projectGraphVersion,
await buildProjectGraph()
);
} catch (e) { } catch (e) {
printErrorMessage(e); printErrorMessage(e);
process.exit(1); process.exit(1);
} }
} }
export async function createProjectGraphAsync( export async function createProjectGraphAsync(): Promise<ProjectGraph> {
projectGraphVersion = '5.0'
): Promise<ProjectGraph> {
const nxJson = readNxJson(); const nxJson = readNxJson();
const useDaemonProcessOption = const useDaemonProcessOption =
nxJson.tasksRunnerOptions?.['default']?.options?.useDaemonProcess; nxJson.tasksRunnerOptions?.['default']?.options?.useDaemonProcess;
@ -93,18 +85,14 @@ export async function createProjectGraphAsync(
(useDaemonProcessOption === false && env === undefined) || (useDaemonProcessOption === false && env === undefined) ||
(useDaemonProcessOption === false && env === 'false') (useDaemonProcessOption === false && env === 'false')
) { ) {
return await buildProjectGraphWithoutDaemon(projectGraphVersion); return await buildProjectGraphWithoutDaemon();
} else { } else {
try { try {
const daemonClient = require('./daemon/client/client'); const daemonClient = require('./daemon/client/client');
if (!(await daemonClient.isServerAvailable())) { if (!(await daemonClient.isServerAvailable())) {
await daemonClient.startInBackground(); await daemonClient.startInBackground();
} }
return projectGraphAdapter( return daemonClient.getProjectGraphFromServer();
'5.0',
projectGraphVersion,
await daemonClient.getProjectGraphFromServer()
);
} catch (e) { } catch (e) {
if (e.message.indexOf('inotify_add_watch') > -1) { if (e.message.indexOf('inotify_add_watch') > -1) {
// common errors with the daemon due to OS settings (cannot watch all the files available) // common errors with the daemon due to OS settings (cannot watch all the files available)
@ -127,7 +115,7 @@ export async function createProjectGraphAsync(
}); });
} }
markDaemonAsDisabled(); markDaemonAsDisabled();
return buildProjectGraphWithoutDaemon(projectGraphVersion); return buildProjectGraphWithoutDaemon();
} }
} }
} }
@ -161,12 +149,12 @@ export function projectGraphAdapter(
sourceVersion: string, sourceVersion: string,
targetVersion: string, targetVersion: string,
projectGraph: ProjectGraph projectGraph: ProjectGraph
): ProjectGraph { ): ProjectGraph | ProjectGraphV4 {
if (sourceVersion === targetVersion) { if (sourceVersion === targetVersion) {
return projectGraph; return projectGraph;
} }
if (sourceVersion === '5.0' && targetVersion === '4.0') { if (sourceVersion === '5.0' && targetVersion === '4.0') {
return projectGraphCompat5to4(projectGraph); return projectGraphCompat5to4(projectGraph as ProjectGraph);
} }
throw new Error( throw new Error(
`Invalid source or target versions. Source: ${sourceVersion}, Target: ${targetVersion}. `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 * @param {ProjectGraph} projectGraph
* @returns {ProjectGraph} * @returns {ProjectGraph}
*/ */
function projectGraphCompat5to4(projectGraph: ProjectGraph): ProjectGraph { function projectGraphCompat5to4(projectGraph: ProjectGraph): ProjectGraphV4 {
const { externalNodes, ...rest } = projectGraph; const { externalNodes, ...rest } = projectGraph;
return { return {
...rest, ...rest,

View File

@ -1,7 +1,10 @@
import { resolveModuleByImport } from '../utilities/typescript'; import { resolveModuleByImport } from '../utilities/typescript';
import { readFileIfExisting } from './file-utils'; import { readFileIfExisting } from './file-utils';
import type { ProjectGraphNode } from '@nrwl/devkit'; import {
import { parseJson, ProjectGraphExternalNode } from '@nrwl/devkit'; parseJson,
ProjectGraphExternalNode,
ProjectGraphProjectNode,
} from '@nrwl/devkit';
import { isRelativePath } from '../utilities/fileutils'; import { isRelativePath } from '../utilities/fileutils';
import { dirname, join, posix } from 'path'; import { dirname, join, posix } from 'path';
import { appRootPath } from '@nrwl/tao/src/utils/app-root'; import { appRootPath } from '@nrwl/tao/src/utils/app-root';
@ -17,7 +20,7 @@ export class TargetProjectLocator {
private npmResolutionCache = new Map<string, string | null>(); private npmResolutionCache = new Map<string, string | null>();
constructor( constructor(
private readonly nodes: Record<string, ProjectGraphNode>, private readonly nodes: Record<string, ProjectGraphProjectNode>,
private readonly externalNodes: Record<string, ProjectGraphExternalNode> private readonly externalNodes: Record<string, ProjectGraphExternalNode>
) {} ) {}
@ -194,7 +197,9 @@ export class TargetProjectLocator {
} }
} }
function createProjectRootMappings(nodes: Record<string, ProjectGraphNode>) { function createProjectRootMappings(
nodes: Record<string, ProjectGraphProjectNode>
) {
const projectRootMappings = new Map(); const projectRootMappings = new Map();
for (const projectName of Object.keys(nodes)) { for (const projectName of Object.keys(nodes)) {
const root = nodes[projectName].data.root; const root = nodes[projectName].data.root;

View File

@ -4,7 +4,7 @@ import { appRootPath } from '@nrwl/tao/src/utils/app-root';
import type { import type {
NxJsonConfiguration, NxJsonConfiguration,
ProjectGraph, ProjectGraph,
ProjectGraphNode, ProjectGraphProjectNode,
TargetDependencyConfig, TargetDependencyConfig,
Task, Task,
} from '@nrwl/devkit'; } from '@nrwl/devkit';
@ -91,7 +91,7 @@ async function getTerminalOutputLifeCycle(
} }
export async function runCommand( export async function runCommand(
projectsToRun: ProjectGraphNode[], projectsToRun: ProjectGraphProjectNode[],
projectGraph: ProjectGraph, projectGraph: ProjectGraph,
{ nxJson }: Environment, { nxJson }: Environment,
nxArgs: NxArgs, nxArgs: NxArgs,
@ -203,7 +203,7 @@ async function anyFailuresInObservable(obs: any) {
} }
interface TaskParams { interface TaskParams {
project: ProjectGraphNode; project: ProjectGraphProjectNode;
target: string; target: string;
configuration: string; configuration: string;
overrides: Object; overrides: Object;
@ -211,7 +211,7 @@ interface TaskParams {
} }
export function createTasksForProjectToRun( export function createTasksForProjectToRun(
projectsToRun: ProjectGraphNode[], projectsToRun: ProjectGraphProjectNode[],
params: Omit<TaskParams, 'project' | 'errorIfCannotFindConfiguration'>, params: Omit<TaskParams, 'project' | 'errorIfCannotFindConfiguration'>,
projectGraph: ProjectGraph, projectGraph: ProjectGraph,
initiatingProject: string | null, initiatingProject: string | null,
@ -345,7 +345,7 @@ export function createTask({
} }
function addTasksForProjectDependencyConfig( function addTasksForProjectDependencyConfig(
project: ProjectGraphNode, project: ProjectGraphProjectNode,
{ {
target, target,
configuration, configuration,
@ -382,10 +382,13 @@ function addTasksForProjectDependencyConfig(
const dependencies = projectGraph.dependencies[project.name]; const dependencies = projectGraph.dependencies[project.name];
if (dependencies) { if (dependencies) {
for (const dep of dependencies) { for (const dep of dependencies) {
const depProject = const depProject = projectGraph.nodes[
projectGraph.nodes[dep.target] || dep.target
projectGraph.externalNodes[dep.target]; ] as ProjectGraphProjectNode;
if (projectHasTarget(depProject, dependencyConfig.target)) { if (
depProject &&
projectHasTarget(depProject, dependencyConfig.target)
) {
addTasksForProjectTarget( addTasksForProjectTarget(
{ {
project: depProject, project: depProject,
@ -405,7 +408,10 @@ function addTasksForProjectDependencyConfig(
if (seenSet.has(dep.target)) { if (seenSet.has(dep.target)) {
continue; continue;
} }
if (!depProject) {
seenSet.add(dep.target);
continue;
}
addTasksForProjectDependencyConfig( addTasksForProjectDependencyConfig(
depProject, depProject,
{ target, configuration, overrides }, { target, configuration, overrides },

View File

@ -1,7 +1,7 @@
import { import {
getPackageManagerCommand, getPackageManagerCommand,
ProjectGraph, ProjectGraph,
ProjectGraphNode, ProjectGraphProjectNode,
TargetDependencyConfig, TargetDependencyConfig,
Task, Task,
TaskGraph, TaskGraph,
@ -51,13 +51,16 @@ export function getDependencyConfigs(
return dependencyConfigs; return dependencyConfigs;
} }
export function getOutputs(p: Record<string, ProjectGraphNode>, task: Task) { export function getOutputs(
p: Record<string, ProjectGraphProjectNode>,
task: Task
) {
return getOutputsForTargetAndConfiguration(task, p[task.target.project]); return getOutputsForTargetAndConfiguration(task, p[task.target.project]);
} }
export function getOutputsForTargetAndConfiguration( export function getOutputsForTargetAndConfiguration(
task: Pick<Task, 'target' | 'overrides'>, task: Pick<Task, 'target' | 'overrides'>,
node: ProjectGraphNode node: ProjectGraphProjectNode
) { ) {
const { target, configuration } = task.target; const { target, configuration } = task.target;

View File

@ -1,14 +1,19 @@
import { isNpmProject, ProjectType } from '../core/project-graph'; import { isNpmProject, ProjectType } from '../core/project-graph';
import { join, resolve, dirname, relative } from 'path'; import { join, resolve, dirname, relative } from 'path';
import { directoryExists } from './fileutils'; import { directoryExists } from './fileutils';
import { stripIndents, readJsonFile, writeJsonFile } from '@nrwl/devkit'; import {
import type { ProjectGraph, ProjectGraphNode } from '@nrwl/devkit'; stripIndents,
readJsonFile,
writeJsonFile,
ProjectGraphExternalNode,
} from '@nrwl/devkit';
import type { ProjectGraph, ProjectGraphProjectNode } from '@nrwl/devkit';
import { getOutputsForTargetAndConfiguration } from '../tasks-runner/utils'; import { getOutputsForTargetAndConfiguration } from '../tasks-runner/utils';
import * as ts from 'typescript'; import * as ts from 'typescript';
import { unlinkSync } from 'fs'; import { unlinkSync } from 'fs';
import { output } from './output'; import { output } from './output';
function isBuildable(target: string, node: ProjectGraphNode): boolean { function isBuildable(target: string, node: ProjectGraphProjectNode): boolean {
return ( return (
node.data.targets && node.data.targets &&
node.data.targets[target] && node.data.targets[target] &&
@ -19,7 +24,7 @@ function isBuildable(target: string, node: ProjectGraphNode): boolean {
export type DependentBuildableProjectNode = { export type DependentBuildableProjectNode = {
name: string; name: string;
outputs: string[]; outputs: string[];
node: ProjectGraphNode; node: ProjectGraphProjectNode | ProjectGraphExternalNode;
}; };
export function calculateProjectDependencies( export function calculateProjectDependencies(
@ -29,7 +34,7 @@ export function calculateProjectDependencies(
targetName: string, targetName: string,
configurationName: string configurationName: string
): { ): {
target: ProjectGraphNode; target: ProjectGraphProjectNode;
dependencies: DependentBuildableProjectNode[]; dependencies: DependentBuildableProjectNode[];
nonBuildableDependencies: string[]; nonBuildableDependencies: string[];
} { } {
@ -255,7 +260,7 @@ export function updateBuildableProjectPackageJsonDependencies(
projectName: string, projectName: string,
targetName: string, targetName: string,
configurationName: string, configurationName: string,
node: ProjectGraphNode, node: ProjectGraphProjectNode,
dependencies: DependentBuildableProjectNode[], dependencies: DependentBuildableProjectNode[],
typeOfDependency: 'dependencies' | 'peerDependencies' = 'dependencies' typeOfDependency: 'dependencies' | 'peerDependencies' = 'dependencies'
) { ) {

View File

@ -1,8 +1,7 @@
import { import {
normalizePath, normalizePath,
NxPlugin,
ProjectGraph, ProjectGraph,
ProjectGraphNode, ProjectGraphProjectNode,
readJsonFile, readJsonFile,
TargetConfiguration, TargetConfiguration,
} from '@nrwl/devkit'; } from '@nrwl/devkit';
@ -10,16 +9,18 @@ import {
buildTargetFromScript, buildTargetFromScript,
PackageJson, PackageJson,
} from '@nrwl/tao/src/shared/package-json'; } from '@nrwl/tao/src/shared/package-json';
import { sync } from 'glob';
import { join, relative } from 'path'; import { join, relative } from 'path';
import { readCachedProjectGraph } from '../core/project-graph'; 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]; return project.data && project.data.targets && project.data.targets[target];
} }
export function projectHasTargetAndConfiguration( export function projectHasTargetAndConfiguration(
project: ProjectGraphNode, project: ProjectGraphProjectNode,
target: string, target: string,
configuration: string configuration: string
) { ) {
@ -111,7 +112,7 @@ function findAllProjectNodeDependencies(
const dependencyNodeNames = new Set<string>(); const dependencyNodeNames = new Set<string>();
collectDependentProjectNodesNames( collectDependentProjectNodesNames(
projectGraph, projectGraph as ProjectGraph,
dependencyNodeNames, dependencyNodeNames,
parentNodeName parentNodeName
); );

View File

@ -1,5 +1,8 @@
import type { FileData, ProjectGraph, ProjectGraphNode } from '@nrwl/devkit'; import type {
import { isWorkspaceProject } from '../core/project-graph/operators'; FileData,
ProjectGraph,
ProjectGraphProjectNode,
} from '@nrwl/devkit';
interface Reach { interface Reach {
graph: ProjectGraph; graph: ProjectGraph;
@ -63,7 +66,7 @@ export function getPath(
graph: ProjectGraph, graph: ProjectGraph,
sourceProjectName: string, sourceProjectName: string,
targetProjectName: string targetProjectName: string
): Array<ProjectGraphNode> { ): Array<ProjectGraphProjectNode> {
if (sourceProjectName === targetProjectName) return []; if (sourceProjectName === targetProjectName) return [];
if (reach.graph !== graph) { if (reach.graph !== graph) {
@ -105,16 +108,16 @@ export function getPath(
export function checkCircularPath( export function checkCircularPath(
graph: ProjectGraph, graph: ProjectGraph,
sourceProject: ProjectGraphNode, sourceProject: ProjectGraphProjectNode,
targetProject: ProjectGraphNode targetProject: ProjectGraphProjectNode
): Array<ProjectGraphNode> { ): Array<ProjectGraphProjectNode> {
if (!graph.nodes[targetProject.name]) return []; if (!graph.nodes[targetProject.name]) return [];
return getPath(graph, targetProject.name, sourceProject.name); return getPath(graph, targetProject.name, sourceProject.name);
} }
export function findFilesInCircularPath( export function findFilesInCircularPath(
circularPath: ProjectGraphNode[] circularPath: ProjectGraphProjectNode[]
): Array<string[]> { ): Array<string[]> {
const filePathChain = []; const filePathChain = [];

View File

@ -3,7 +3,6 @@ import { FileData, readFileIfExisting } from '../core/file-utils';
import { import {
ProjectGraph, ProjectGraph,
ProjectGraphDependency, ProjectGraphDependency,
ProjectGraphNode,
ProjectGraphProjectNode, ProjectGraphProjectNode,
normalizePath, normalizePath,
DependencyType, DependencyType,
@ -31,13 +30,13 @@ export type DepConstraint = {
}; };
export function hasNoneOfTheseTags( export function hasNoneOfTheseTags(
proj: ProjectGraphNode<any>, proj: ProjectGraphProjectNode<any>,
tags: string[] tags: string[]
) { ) {
return tags.filter((allowedTag) => hasTag(proj, allowedTag)).length === 0; 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; return tag === '*' || (proj.data.tags || []).indexOf(tag) > -1;
} }
@ -76,7 +75,7 @@ export function isRelativeImportIntoAnotherProject(
projectPath: string, projectPath: string,
projectGraph: MappedProjectGraph, projectGraph: MappedProjectGraph,
sourceFilePath: string, sourceFilePath: string,
sourceProject: ProjectGraphNode sourceProject: ProjectGraphProjectNode
): boolean { ): boolean {
if (!isRelative(imp)) return false; if (!isRelative(imp)) return false;
@ -152,7 +151,7 @@ export function findProjectUsingImport(
export function findConstraintsFor( export function findConstraintsFor(
depConstraints: DepConstraint[], depConstraints: DepConstraint[],
sourceProject: ProjectGraphNode sourceProject: ProjectGraphProjectNode
) { ) {
return depConstraints.filter((f) => hasTag(sourceProject, f.sourceTag)); return depConstraints.filter((f) => hasTag(sourceProject, f.sourceTag));
} }
@ -181,8 +180,8 @@ export function getSourceFilePath(sourceFileName: string, projectPath: string) {
} }
export function hasBannedImport( export function hasBannedImport(
source: ProjectGraphNode, source: ProjectGraphProjectNode,
target: ProjectGraphNode, target: ProjectGraphProjectNode | ProjectGraphExternalNode,
depConstraints: DepConstraint[] depConstraints: DepConstraint[]
): DepConstraint | null { ): DepConstraint | null {
// return those constraints that match source projec and have `bannedExternalImports` defined // 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 * Verifies whether the given node has an architect builder attached
* @param projectGraph the node to verify * @param projectGraph the node to verify
*/ */
export function hasBuildExecutor(projectGraph: ProjectGraphNode): boolean { export function hasBuildExecutor(
projectGraph: ProjectGraphProjectNode
): boolean {
return ( return (
// can the architect not be defined? real use case? // can the architect not be defined? real use case?
projectGraph.data.targets && projectGraph.data.targets &&