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
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',

View File

@ -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<string, ProjectGraphDependency[]>,
@ -341,7 +344,7 @@ export class GraphService {
}
private generateCytoscapeLayout(
allProjects: ProjectGraphNode[],
allProjects: ProjectGraphProjectNode[],
groupByFolder: boolean,
workspaceLayout,
dependencies: Record<string, ProjectGraphDependency[]>,
@ -364,7 +367,7 @@ export class GraphService {
}
private createElements(
projects: ProjectGraphNode[],
projects: ProjectGraphProjectNode[],
groupByFolder: boolean,
workspaceLayout: {
appsDir: string;

View File

@ -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<string, ProjectGraphDependency[]>;
affectedProjects: string[];
workspaceLayout: {
@ -53,7 +56,7 @@ export type DepGraphUIEvents =
}
| {
type: 'updateGraph';
projects: ProjectGraphNode[];
projects: ProjectGraphProjectNode[];
dependencies: Record<string, ProjectGraphDependency[]>;
};
@ -62,7 +65,7 @@ export type DepGraphUIEvents =
export type GraphRenderEvents =
| {
type: 'notifyGraphInitGraph';
projects: ProjectGraphNode[];
projects: ProjectGraphProjectNode[];
dependencies: Record<string, ProjectGraphDependency[]>;
affectedProjects: string[];
workspaceLayout: {
@ -73,7 +76,7 @@ export type GraphRenderEvents =
}
| {
type: 'notifyGraphUpdateGraph';
projects: ProjectGraphNode[];
projects: ProjectGraphProjectNode[];
dependencies: Record<string, ProjectGraphDependency[]>;
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<string, ProjectGraphDependency[]>;
affectedProjects: 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 { WorkspaceLayout } from '../interfaces';
import { GraphPerfReport } from './interfaces';
export const allProjectsSelector: DepGraphSelector<ProjectGraphNode[]> = (
state
) => state.context.projects;
export const allProjectsSelector: DepGraphSelector<
ProjectGraphProjectNode[]
> = (state) => state.context.projects;
export const workspaceLayoutSelector: DepGraphSelector<WorkspaceLayout> = (
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
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}`;

View File

@ -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
) {}

View File

@ -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

View File

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

View File

@ -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

View File

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

View File

@ -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
) {

View File

@ -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));
}

View File

@ -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<string, ProjectGraphDependency[]>;
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<string>;
@ -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);
});

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 { 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

View File

@ -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)) {

View File

@ -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];

View File

@ -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';

View File

@ -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>): ProjectGraphCache {
const defaults: ProjectGraphCache = {
version: '3.0',
version: '5.0',
deps: {
'@nrwl/workspace': '12.0.0',
plugin: '1.0.0',

View File

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

View File

@ -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<string, ProjectGraphNode>;
let projects: Record<string, ProjectGraphProjectNode>;
let fsJson;
beforeEach(() => {
const workspaceJson = {

View File

@ -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);

View File

@ -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<string, ProjectGraphNode>;
let projects: Record<string, ProjectGraphProjectNode>;
let fsJson;
beforeEach(() => {
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 { 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;

View File

@ -3,7 +3,6 @@ import {
logger,
NxJsonConfiguration,
NxJsonProjectConfiguration,
NxPlugin,
ProjectConfiguration,
ProjectFileMap,
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
*/
export function isWorkspaceProject(project: ProjectGraphNode) {
export function isWorkspaceProject(
project: ProjectGraphNode
): project is ProjectGraphProjectNode {
return (
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 {
ProjectGraph,
ProjectGraphDependency,
ProjectGraphNode,
ProjectGraphProjectNode,
DependencyType,
} from '@nrwl/devkit';
export type ProjectGraphNodeRecords = Record<string, ProjectGraphNode>;
export type ProjectGraphNodeRecords = Record<string, ProjectGraphProjectNode>;
export enum ProjectType {
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 { 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<ProjectGraph> {
export async function createProjectGraphAsync(): Promise<ProjectGraph> {
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,

View File

@ -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<string, string | null>();
constructor(
private readonly nodes: Record<string, ProjectGraphNode>,
private readonly nodes: Record<string, ProjectGraphProjectNode>,
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();
for (const projectName of Object.keys(nodes)) {
const root = nodes[projectName].data.root;

View File

@ -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<TaskParams, 'project' | 'errorIfCannotFindConfiguration'>,
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 },

View File

@ -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<string, ProjectGraphNode>, task: Task) {
export function getOutputs(
p: Record<string, ProjectGraphProjectNode>,
task: Task
) {
return getOutputsForTargetAndConfiguration(task, p[task.target.project]);
}
export function getOutputsForTargetAndConfiguration(
task: Pick<Task, 'target' | 'overrides'>,
node: ProjectGraphNode
node: ProjectGraphProjectNode
) {
const { target, configuration } = task.target;

View File

@ -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'
) {

View File

@ -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<string>();
collectDependentProjectNodesNames(
projectGraph,
projectGraph as ProjectGraph,
dependencyNodeNames,
parentNodeName
);

View File

@ -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<ProjectGraphNode> {
): Array<ProjectGraphProjectNode> {
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<ProjectGraphNode> {
sourceProject: ProjectGraphProjectNode,
targetProject: ProjectGraphProjectNode
): Array<ProjectGraphProjectNode> {
if (!graph.nodes[targetProject.name]) return [];
return getPath(graph, targetProject.name, sourceProject.name);
}
export function findFilesInCircularPath(
circularPath: ProjectGraphNode[]
circularPath: ProjectGraphProjectNode[]
): Array<string[]> {
const filePathChain = [];

View File

@ -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<any>,
proj: ProjectGraphProjectNode<any>,
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 &&