parent
be8ce09ddb
commit
31bb2f3626
@ -1,5 +1,9 @@
|
|||||||
// nx-ignore-next-line
|
// nx-ignore-next-line
|
||||||
import type { ProjectGraphDependency, ProjectGraphNode } from '@nrwl/devkit';
|
import {
|
||||||
|
DependencyType,
|
||||||
|
ProjectGraphDependency,
|
||||||
|
ProjectGraphNode,
|
||||||
|
} from '@nrwl/devkit';
|
||||||
import { depGraphMachine } from './dep-graph.machine';
|
import { depGraphMachine } from './dep-graph.machine';
|
||||||
import { interpret } from 'xstate';
|
import { interpret } from 'xstate';
|
||||||
|
|
||||||
@ -51,38 +55,38 @@ export const mockProjects: ProjectGraphNode[] = [
|
|||||||
export const mockDependencies: Record<string, ProjectGraphDependency[]> = {
|
export const mockDependencies: Record<string, ProjectGraphDependency[]> = {
|
||||||
app1: [
|
app1: [
|
||||||
{
|
{
|
||||||
type: 'static',
|
type: DependencyType.static,
|
||||||
source: 'app1',
|
source: 'app1',
|
||||||
target: 'auth-lib',
|
target: 'auth-lib',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'static',
|
type: DependencyType.static,
|
||||||
source: 'app1',
|
source: 'app1',
|
||||||
target: 'feature-lib1',
|
target: 'feature-lib1',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
app2: [
|
app2: [
|
||||||
{
|
{
|
||||||
type: 'static',
|
type: DependencyType.static,
|
||||||
source: 'app2',
|
source: 'app2',
|
||||||
target: 'auth-lib',
|
target: 'auth-lib',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'static',
|
type: DependencyType.static,
|
||||||
source: 'app2',
|
source: 'app2',
|
||||||
target: 'feature-lib2',
|
target: 'feature-lib2',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
'feature-lib1': [
|
'feature-lib1': [
|
||||||
{
|
{
|
||||||
type: 'static',
|
type: DependencyType.static,
|
||||||
source: 'feature-lib1',
|
source: 'feature-lib1',
|
||||||
target: 'ui-lib',
|
target: 'ui-lib',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
'feature-lib2': [
|
'feature-lib2': [
|
||||||
{
|
{
|
||||||
type: 'static',
|
type: DependencyType.static,
|
||||||
source: 'feature-lib2',
|
source: 'feature-lib2',
|
||||||
target: 'ui-lib',
|
target: 'ui-lib',
|
||||||
},
|
},
|
||||||
|
|||||||
@ -33,7 +33,7 @@ export class MockProjectGraphService implements ProjectGraphService {
|
|||||||
{
|
{
|
||||||
source: 'existing-app-1',
|
source: 'existing-app-1',
|
||||||
target: 'existing-lib-1',
|
target: 'existing-lib-1',
|
||||||
type: 'statis',
|
type: 'static' as any,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
'existing-lib-1': [],
|
'existing-lib-1': [],
|
||||||
@ -82,7 +82,7 @@ export class MockProjectGraphService implements ProjectGraphService {
|
|||||||
{
|
{
|
||||||
source: newProject.name,
|
source: newProject.name,
|
||||||
target: targetDependency.name,
|
target: targetDependency.name,
|
||||||
type: 'static',
|
type: 'static' as any,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@ -41,9 +41,22 @@ const dynamicEdges: Stylesheet = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const typeOnlyEdges: Stylesheet = {
|
||||||
|
selector: 'edge.typeOnly',
|
||||||
|
style: {
|
||||||
|
label: 'type only',
|
||||||
|
'font-size': '16px',
|
||||||
|
'edge-text-rotation': 'autorotate',
|
||||||
|
'curve-style': 'unbundled-bezier',
|
||||||
|
'line-dash-pattern': [5, 5],
|
||||||
|
'line-style': 'dashed',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
export const edgeStyles: Stylesheet[] = [
|
export const edgeStyles: Stylesheet[] = [
|
||||||
allEdges,
|
allEdges,
|
||||||
affectedEdges,
|
affectedEdges,
|
||||||
implicitEdges,
|
implicitEdges,
|
||||||
dynamicEdges,
|
dynamicEdges,
|
||||||
|
typeOnlyEdges,
|
||||||
];
|
];
|
||||||
|
|||||||
@ -185,7 +185,7 @@
|
|||||||
{
|
{
|
||||||
"source": "shared-product-data",
|
"source": "shared-product-data",
|
||||||
"target": "shared-product-types",
|
"target": "shared-product-types",
|
||||||
"type": "static"
|
"type": "typeOnly"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"products-home-page": [
|
"products-home-page": [
|
||||||
|
|||||||
@ -36,6 +36,7 @@ It only uses language primitives and immutable objects
|
|||||||
- [FileData](../../generated/nx-devkit/index#filedata)
|
- [FileData](../../generated/nx-devkit/index#filedata)
|
||||||
- [ProjectFileMap](../../generated/nx-devkit/index#projectfilemap)
|
- [ProjectFileMap](../../generated/nx-devkit/index#projectfilemap)
|
||||||
- [ProjectGraph](../../generated/nx-devkit/index#projectgraph)
|
- [ProjectGraph](../../generated/nx-devkit/index#projectgraph)
|
||||||
|
- [ProjectGraphBuilderExplicitDependency](../../generated/nx-devkit/index#projectgraphbuilderexplicitdependency)
|
||||||
- [ProjectGraphDependency](../../generated/nx-devkit/index#projectgraphdependency)
|
- [ProjectGraphDependency](../../generated/nx-devkit/index#projectgraphdependency)
|
||||||
- [ProjectGraphExternalNode](../../generated/nx-devkit/index#projectgraphexternalnode)
|
- [ProjectGraphExternalNode](../../generated/nx-devkit/index#projectgraphexternalnode)
|
||||||
- [ProjectGraphProcessorContext](../../generated/nx-devkit/index#projectgraphprocessorcontext)
|
- [ProjectGraphProcessorContext](../../generated/nx-devkit/index#projectgraphprocessorcontext)
|
||||||
@ -210,6 +211,12 @@ A plugin for Nx
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
### ProjectGraphBuilderExplicitDependency
|
||||||
|
|
||||||
|
• **ProjectGraphBuilderExplicitDependency**: `Object`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### ProjectGraphDependency
|
### ProjectGraphDependency
|
||||||
|
|
||||||
• **ProjectGraphDependency**: `Object`
|
• **ProjectGraphDependency**: `Object`
|
||||||
|
|||||||
@ -273,7 +273,7 @@ describe('dep-graph', () => {
|
|||||||
target: mylib,
|
target: mylib,
|
||||||
type: 'static',
|
type: 'static',
|
||||||
},
|
},
|
||||||
{ source: myapp, target: mylib2, type: 'static' },
|
{ source: myapp, target: mylib2, type: 'dynamic' },
|
||||||
],
|
],
|
||||||
[myappE2e]: [
|
[myappE2e]: [
|
||||||
{
|
{
|
||||||
|
|||||||
@ -36,6 +36,7 @@ It only uses language primitives and immutable objects
|
|||||||
- [FileData](../../generated/nx-devkit/index#filedata)
|
- [FileData](../../generated/nx-devkit/index#filedata)
|
||||||
- [ProjectFileMap](../../generated/nx-devkit/index#projectfilemap)
|
- [ProjectFileMap](../../generated/nx-devkit/index#projectfilemap)
|
||||||
- [ProjectGraph](../../generated/nx-devkit/index#projectgraph)
|
- [ProjectGraph](../../generated/nx-devkit/index#projectgraph)
|
||||||
|
- [ProjectGraphBuilderExplicitDependency](../../generated/nx-devkit/index#projectgraphbuilderexplicitdependency)
|
||||||
- [ProjectGraphDependency](../../generated/nx-devkit/index#projectgraphdependency)
|
- [ProjectGraphDependency](../../generated/nx-devkit/index#projectgraphdependency)
|
||||||
- [ProjectGraphExternalNode](../../generated/nx-devkit/index#projectgraphexternalnode)
|
- [ProjectGraphExternalNode](../../generated/nx-devkit/index#projectgraphexternalnode)
|
||||||
- [ProjectGraphProcessorContext](../../generated/nx-devkit/index#projectgraphprocessorcontext)
|
- [ProjectGraphProcessorContext](../../generated/nx-devkit/index#projectgraphprocessorcontext)
|
||||||
@ -210,6 +211,12 @@ A plugin for Nx
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
### ProjectGraphBuilderExplicitDependency
|
||||||
|
|
||||||
|
• **ProjectGraphBuilderExplicitDependency**: `Object`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### ProjectGraphDependency
|
### ProjectGraphDependency
|
||||||
|
|
||||||
• **ProjectGraphDependency**: `Object`
|
• **ProjectGraphDependency**: `Object`
|
||||||
|
|||||||
@ -144,6 +144,7 @@ export type {
|
|||||||
ProjectFileMap,
|
ProjectFileMap,
|
||||||
FileData,
|
FileData,
|
||||||
ProjectGraph,
|
ProjectGraph,
|
||||||
|
ProjectGraphBuilderExplicitDependency,
|
||||||
ProjectGraphDependency,
|
ProjectGraphDependency,
|
||||||
ProjectGraphNode,
|
ProjectGraphNode,
|
||||||
ProjectGraphProjectNode,
|
ProjectGraphProjectNode,
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import { DependencyType } from './interfaces';
|
||||||
import { ProjectGraphBuilder } from './project-graph-builder';
|
import { ProjectGraphBuilder } from './project-graph-builder';
|
||||||
|
|
||||||
describe('ProjectGraphBuilder', () => {
|
describe('ProjectGraphBuilder', () => {
|
||||||
@ -96,21 +97,77 @@ describe('ProjectGraphBuilder', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it(`should use implicit dep when both implicit and explicit deps are available`, () => {
|
describe('dependency type priority', () => {
|
||||||
// don't include duplicates
|
it(`should use implicit dep when both implicit and explicit deps are available`, () => {
|
||||||
builder.addImplicitDependency('source', 'target');
|
// don't include duplicates
|
||||||
builder.addExplicitDependency('source', 'source/index.ts', 'target');
|
builder.addImplicitDependency('source', 'target');
|
||||||
|
builder.addExplicitDependency('source', 'source/index.ts', 'target');
|
||||||
|
|
||||||
const graph = builder.getUpdatedProjectGraph();
|
const graph = builder.getUpdatedProjectGraph();
|
||||||
expect(graph.dependencies).toEqual({
|
expect(graph.dependencies).toEqual({
|
||||||
source: [
|
source: [
|
||||||
{
|
{
|
||||||
source: 'source',
|
source: 'source',
|
||||||
target: 'target',
|
target: 'target',
|
||||||
type: 'implicit',
|
type: 'implicit',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
target: [],
|
target: [],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`should use explicit deps in priority order "static > dynamic"`, () => {
|
||||||
|
builder.addExplicitDependency(
|
||||||
|
'source',
|
||||||
|
'source/index.ts',
|
||||||
|
'target',
|
||||||
|
DependencyType.dynamic
|
||||||
|
);
|
||||||
|
builder.addExplicitDependency(
|
||||||
|
'source',
|
||||||
|
'source/index.ts',
|
||||||
|
'target',
|
||||||
|
DependencyType.static
|
||||||
|
);
|
||||||
|
|
||||||
|
const graph = builder.getUpdatedProjectGraph();
|
||||||
|
expect(graph.dependencies).toEqual({
|
||||||
|
source: [
|
||||||
|
{
|
||||||
|
source: 'source',
|
||||||
|
target: 'target',
|
||||||
|
type: DependencyType.static,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
target: [],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`should use explicit deps in priority order "dynamic > type-only"`, () => {
|
||||||
|
builder.addExplicitDependency(
|
||||||
|
'source',
|
||||||
|
'source/index.ts',
|
||||||
|
'target',
|
||||||
|
DependencyType.dynamic
|
||||||
|
);
|
||||||
|
builder.addExplicitDependency(
|
||||||
|
'source',
|
||||||
|
'source/second.ts',
|
||||||
|
'target',
|
||||||
|
DependencyType.typeOnly
|
||||||
|
);
|
||||||
|
|
||||||
|
const graph = builder.getUpdatedProjectGraph();
|
||||||
|
expect(graph.dependencies).toEqual({
|
||||||
|
source: [
|
||||||
|
{
|
||||||
|
source: 'source',
|
||||||
|
target: 'target',
|
||||||
|
type: DependencyType.dynamic,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
target: [],
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import type {
|
import type {
|
||||||
|
FileData,
|
||||||
ProjectGraph,
|
ProjectGraph,
|
||||||
ProjectGraphDependency,
|
ProjectGraphDependency,
|
||||||
ProjectGraphExternalNode,
|
ProjectGraphExternalNode,
|
||||||
@ -110,7 +111,8 @@ export class ProjectGraphBuilder {
|
|||||||
addExplicitDependency(
|
addExplicitDependency(
|
||||||
sourceProjectName: string,
|
sourceProjectName: string,
|
||||||
sourceProjectFile: string,
|
sourceProjectFile: string,
|
||||||
targetProjectName: string
|
targetProjectName: string,
|
||||||
|
dependencyType: DependencyType = DependencyType.static // TODO: Make this argument required
|
||||||
): void {
|
): void {
|
||||||
if (sourceProjectName === targetProjectName) {
|
if (sourceProjectName === targetProjectName) {
|
||||||
return;
|
return;
|
||||||
@ -127,9 +129,8 @@ export class ProjectGraphBuilder {
|
|||||||
throw new Error(`Target project does not exist: ${targetProjectName}`);
|
throw new Error(`Target project does not exist: ${targetProjectName}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const fileData = source.data.files.find(
|
const files = source.data.files as FileData[];
|
||||||
(f) => f.file === sourceProjectFile
|
const fileData = files.find((f) => f.file === sourceProjectFile);
|
||||||
);
|
|
||||||
if (!fileData) {
|
if (!fileData) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Source project ${sourceProjectName} does not have a file: ${sourceProjectFile}`
|
`Source project ${sourceProjectName} does not have a file: ${sourceProjectFile}`
|
||||||
@ -140,8 +141,19 @@ export class ProjectGraphBuilder {
|
|||||||
fileData.deps = [];
|
fileData.deps = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fileData.deps.find((t) => t === targetProjectName)) {
|
const existingFileDep = fileData.deps.find(
|
||||||
fileData.deps.push(targetProjectName);
|
(t) => t.projectName === targetProjectName
|
||||||
|
);
|
||||||
|
if (existingFileDep) {
|
||||||
|
existingFileDep.dependencyType = this.getHigherPriorityDepType(
|
||||||
|
existingFileDep.dependencyType,
|
||||||
|
dependencyType
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
fileData.deps.push({
|
||||||
|
projectName: targetProjectName,
|
||||||
|
dependencyType,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,54 +165,76 @@ export class ProjectGraphBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getUpdatedProjectGraph(): ProjectGraph {
|
getUpdatedProjectGraph(): ProjectGraph {
|
||||||
|
const isRemoved = (sourceProject: string, targetProject: string) =>
|
||||||
|
this.removedEdges[sourceProject] &&
|
||||||
|
this.removedEdges[sourceProject].has(targetProject);
|
||||||
for (const sourceProject of Object.keys(this.graph.nodes)) {
|
for (const sourceProject of Object.keys(this.graph.nodes)) {
|
||||||
const alreadySetTargetProjects =
|
const sourceProjectDepMap = new Map<string, ProjectGraphDependency>(
|
||||||
this.calculateAlreadySetTargetDeps(sourceProject);
|
this.graph.dependencies[sourceProject]
|
||||||
this.graph.dependencies[sourceProject] = [
|
.map((dep) => [dep.target, dep] as const)
|
||||||
...alreadySetTargetProjects.values(),
|
.filter(([targetProject]) => !isRemoved(sourceProject, targetProject))
|
||||||
];
|
);
|
||||||
|
|
||||||
const fileDeps = this.calculateTargetDepsFromFiles(sourceProject);
|
const fileDeps = this.calculateTargetDepsFromFiles(sourceProject);
|
||||||
for (const targetProject of fileDeps) {
|
for (const [targetProject, targetProjectDepType] of fileDeps) {
|
||||||
if (!alreadySetTargetProjects.has(targetProject)) {
|
if (sourceProjectDepMap.has(targetProject)) {
|
||||||
if (
|
const existingDep = sourceProjectDepMap.get(targetProject);
|
||||||
!this.removedEdges[sourceProject] ||
|
existingDep.type = this.getHigherPriorityDepType(
|
||||||
!this.removedEdges[sourceProject].has(targetProject)
|
existingDep.type,
|
||||||
) {
|
targetProjectDepType
|
||||||
this.graph.dependencies[sourceProject].push({
|
);
|
||||||
source: sourceProject,
|
} else if (!isRemoved(sourceProject, targetProject)) {
|
||||||
target: targetProject,
|
sourceProjectDepMap.set(targetProject, {
|
||||||
type: DependencyType.static,
|
source: sourceProject,
|
||||||
});
|
target: targetProject,
|
||||||
}
|
type: targetProjectDepType,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.graph.dependencies[sourceProject] = [
|
||||||
|
...sourceProjectDepMap.values(),
|
||||||
|
];
|
||||||
}
|
}
|
||||||
return this.graph;
|
return this.graph;
|
||||||
}
|
}
|
||||||
|
|
||||||
private calculateTargetDepsFromFiles(sourceProject: string) {
|
private calculateTargetDepsFromFiles(sourceProject: string) {
|
||||||
const fileDeps = new Set<string>();
|
const fileDeps = new Map<string, DependencyType>();
|
||||||
const files = this.graph.nodes[sourceProject].data.files;
|
const files: FileData[] = this.graph.nodes[sourceProject].data.files;
|
||||||
if (!files) return fileDeps;
|
if (!files) return fileDeps;
|
||||||
for (let f of files) {
|
for (let f of files) {
|
||||||
if (f.deps) {
|
if (f.deps) {
|
||||||
for (let p of f.deps) {
|
for (let p of f.deps) {
|
||||||
fileDeps.add(p);
|
if (fileDeps.has(p.projectName)) {
|
||||||
|
const existingDepType = fileDeps.get(p.projectName);
|
||||||
|
const priorityDepType = this.getHigherPriorityDepType(
|
||||||
|
p.dependencyType,
|
||||||
|
existingDepType
|
||||||
|
);
|
||||||
|
fileDeps.set(p.projectName, priorityDepType);
|
||||||
|
} else {
|
||||||
|
fileDeps.set(p.projectName, p.dependencyType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return fileDeps;
|
return fileDeps;
|
||||||
}
|
}
|
||||||
|
|
||||||
private calculateAlreadySetTargetDeps(sourceProject: string) {
|
private getHigherPriorityDepType(
|
||||||
const alreadySetTargetProjects = new Map<string, ProjectGraphDependency>();
|
depTypeA: DependencyType,
|
||||||
const removed = this.removedEdges[sourceProject];
|
depTypeB: DependencyType
|
||||||
for (const d of this.graph.dependencies[sourceProject]) {
|
): DependencyType {
|
||||||
if (!removed || !removed.has(d.target)) {
|
for (const priorityDepType of [
|
||||||
alreadySetTargetProjects.set(d.target, d);
|
DependencyType.implicit,
|
||||||
|
DependencyType.static,
|
||||||
|
DependencyType.dynamic,
|
||||||
|
DependencyType.typeOnly,
|
||||||
|
]) {
|
||||||
|
if (depTypeA === priorityDepType || depTypeB === priorityDepType) {
|
||||||
|
return priorityDepType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return alreadySetTargetProjects;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1661,7 +1661,16 @@ linter.defineParser('@typescript-eslint/parser', parser);
|
|||||||
linter.defineRule(enforceModuleBoundariesRuleName, enforceModuleBoundaries);
|
linter.defineRule(enforceModuleBoundariesRuleName, enforceModuleBoundaries);
|
||||||
|
|
||||||
function createFile(f: string, deps?: string[]): FileData {
|
function createFile(f: string, deps?: string[]): FileData {
|
||||||
return { file: f, hash: '', ...(deps && { deps }) };
|
return {
|
||||||
|
file: f,
|
||||||
|
hash: '',
|
||||||
|
...(deps && {
|
||||||
|
deps: deps.map((dep) => ({
|
||||||
|
projectName: dep,
|
||||||
|
dependencyType: DependencyType.static,
|
||||||
|
})),
|
||||||
|
}),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function runRule(
|
function runRule(
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { ExecutorContext } from '@nrwl/devkit';
|
import { DependencyType, ExecutorContext } from '@nrwl/devkit';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
import { mocked } from 'ts-jest/utils';
|
import { mocked } from 'ts-jest/utils';
|
||||||
|
|
||||||
@ -309,7 +309,7 @@ describe('NodePackageBuilder', () => {
|
|||||||
dependencies: {
|
dependencies: {
|
||||||
nodelib: [
|
nodelib: [
|
||||||
{
|
{
|
||||||
type: ProjectType.lib,
|
type: DependencyType.static,
|
||||||
target: 'nodelib-child',
|
target: 'nodelib-child',
|
||||||
source: null,
|
source: null,
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { findAllNpmDependencies } from './find-all-npm-dependencies';
|
import { findAllNpmDependencies } from './find-all-npm-dependencies';
|
||||||
import { ProjectGraph } from '@nrwl/devkit';
|
import { DependencyType, ProjectGraph } from '@nrwl/devkit';
|
||||||
|
|
||||||
test('findAllNpmDependencies', () => {
|
test('findAllNpmDependencies', () => {
|
||||||
const graph: ProjectGraph = {
|
const graph: ProjectGraph = {
|
||||||
@ -61,26 +61,34 @@ test('findAllNpmDependencies', () => {
|
|||||||
},
|
},
|
||||||
dependencies: {
|
dependencies: {
|
||||||
myapp: [
|
myapp: [
|
||||||
{ type: 'static', source: 'myapp', target: 'lib1' },
|
{ type: DependencyType.static, source: 'myapp', target: 'lib1' },
|
||||||
{ type: 'static', source: 'myapp', target: 'lib2' },
|
{ type: DependencyType.static, source: 'myapp', target: 'lib2' },
|
||||||
{
|
{
|
||||||
type: 'static',
|
type: DependencyType.static,
|
||||||
source: 'myapp',
|
source: 'myapp',
|
||||||
target: 'npm:react-native-image-picker',
|
target: 'npm:react-native-image-picker',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'static',
|
type: DependencyType.static,
|
||||||
source: 'myapp',
|
source: 'myapp',
|
||||||
target: 'npm:@nrwl/react-native',
|
target: 'npm:@nrwl/react-native',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
lib1: [
|
lib1: [
|
||||||
{ type: 'static', source: 'lib1', target: 'lib2' },
|
{ type: DependencyType.static, source: 'lib1', target: 'lib2' },
|
||||||
{ type: 'static', source: 'lib3', target: 'npm:react-native-snackbar' },
|
{
|
||||||
|
type: DependencyType.static,
|
||||||
|
source: 'lib3',
|
||||||
|
target: 'npm:react-native-snackbar',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
lib2: [{ type: 'static', source: 'lib2', target: 'lib3' }],
|
lib2: [{ type: DependencyType.static, source: 'lib2', target: 'lib3' }],
|
||||||
lib3: [
|
lib3: [
|
||||||
{ type: 'static', source: 'lib3', target: 'npm:react-native-dialog' },
|
{
|
||||||
|
type: DependencyType.static,
|
||||||
|
source: 'lib3',
|
||||||
|
target: 'npm:react-native-dialog',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -11,7 +11,19 @@ export interface FileData {
|
|||||||
hash: string;
|
hash: string;
|
||||||
/** @deprecated this field will be removed in v13. Use {@link path.extname} to parse extension */
|
/** @deprecated this field will be removed in v13. Use {@link path.extname} to parse extension */
|
||||||
ext?: string;
|
ext?: string;
|
||||||
deps?: string[];
|
deps?: FileDependency[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FileDependency {
|
||||||
|
projectName: string;
|
||||||
|
dependencyType: DependencyType;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ProjectGraphBuilderExplicitDependency {
|
||||||
|
sourceProjectName: string;
|
||||||
|
targetProjectName: string;
|
||||||
|
sourceProjectFile: string;
|
||||||
|
dependencyType: DependencyType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -49,6 +61,10 @@ export enum DependencyType {
|
|||||||
* Implicit dependencies are inferred
|
* Implicit dependencies are inferred
|
||||||
*/
|
*/
|
||||||
implicit = 'implicit',
|
implicit = 'implicit',
|
||||||
|
/**
|
||||||
|
* Type-only dependencies are those of the form `import type ...`
|
||||||
|
*/
|
||||||
|
typeOnly = 'typeOnly',
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -108,7 +124,7 @@ export interface ProjectGraphExternalNode {
|
|||||||
* A dependency between two projects
|
* A dependency between two projects
|
||||||
*/
|
*/
|
||||||
export interface ProjectGraphDependency {
|
export interface ProjectGraphDependency {
|
||||||
type: DependencyType | string;
|
type: DependencyType;
|
||||||
/**
|
/**
|
||||||
* The project being imported by the other
|
* The project being imported by the other
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -246,7 +246,9 @@ describe('Hasher', () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
dependencies: {
|
dependencies: {
|
||||||
parent: [{ source: 'parent', target: 'child', type: 'static' }],
|
parent: [
|
||||||
|
{ source: 'parent', target: 'child', type: DependencyType.static },
|
||||||
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{} as any,
|
{} as any,
|
||||||
@ -343,8 +345,12 @@ describe('Hasher', () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
dependencies: {
|
dependencies: {
|
||||||
parent: [{ source: 'parent', target: 'child', type: 'static' }],
|
parent: [
|
||||||
child: [{ source: 'child', target: 'parent', type: 'static' }],
|
{ source: 'parent', target: 'child', type: DependencyType.static },
|
||||||
|
],
|
||||||
|
child: [
|
||||||
|
{ source: 'child', target: 'parent', type: DependencyType.static },
|
||||||
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{} as any,
|
{} as any,
|
||||||
|
|||||||
@ -1,4 +1,9 @@
|
|||||||
import { ProjectFileMap, ProjectGraph, Workspace } from '@nrwl/devkit';
|
import {
|
||||||
|
ProjectFileMap,
|
||||||
|
ProjectGraph,
|
||||||
|
ProjectGraphBuilderExplicitDependency,
|
||||||
|
Workspace,
|
||||||
|
} from '@nrwl/devkit';
|
||||||
import { buildExplicitTypeScriptDependencies } from './explicit-project-dependencies';
|
import { buildExplicitTypeScriptDependencies } from './explicit-project-dependencies';
|
||||||
import { buildExplicitPackageJsonDependencies } from './explicit-package-json-dependencies';
|
import { buildExplicitPackageJsonDependencies } from './explicit-package-json-dependencies';
|
||||||
|
|
||||||
@ -10,7 +15,7 @@ export function buildExplicitTypescriptAndPackageJsonDependencies(
|
|||||||
workspace: Workspace,
|
workspace: Workspace,
|
||||||
projectGraph: ProjectGraph,
|
projectGraph: ProjectGraph,
|
||||||
filesToProcess: ProjectFileMap
|
filesToProcess: ProjectFileMap
|
||||||
) {
|
): ProjectGraphBuilderExplicitDependency[] {
|
||||||
let res = [];
|
let res = [];
|
||||||
if (
|
if (
|
||||||
jsPluginConfig.analyzeSourceFiles === undefined ||
|
jsPluginConfig.analyzeSourceFiles === undefined ||
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import { buildExplicitPackageJsonDependencies } from './explicit-package-json-de
|
|||||||
import { vol } from 'memfs';
|
import { vol } from 'memfs';
|
||||||
import { ProjectGraphNode } from '../project-graph-models';
|
import { ProjectGraphNode } from '../project-graph-models';
|
||||||
import {
|
import {
|
||||||
|
DependencyType,
|
||||||
ProjectGraphBuilder,
|
ProjectGraphBuilder,
|
||||||
ProjectGraphProcessorContext,
|
ProjectGraphProcessorContext,
|
||||||
} from '@nrwl/devkit';
|
} from '@nrwl/devkit';
|
||||||
@ -125,16 +126,19 @@ describe('explicit package json dependencies', () => {
|
|||||||
sourceProjectName: 'proj',
|
sourceProjectName: 'proj',
|
||||||
targetProjectName: 'proj2',
|
targetProjectName: 'proj2',
|
||||||
sourceProjectFile: 'libs/proj/package.json',
|
sourceProjectFile: 'libs/proj/package.json',
|
||||||
|
dependencyType: DependencyType.static,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
sourceProjectFile: 'libs/proj/package.json',
|
sourceProjectFile: 'libs/proj/package.json',
|
||||||
sourceProjectName: 'proj',
|
sourceProjectName: 'proj',
|
||||||
targetProjectName: 'npm:external',
|
targetProjectName: 'npm:external',
|
||||||
|
dependencyType: DependencyType.static,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
sourceProjectName: 'proj',
|
sourceProjectName: 'proj',
|
||||||
targetProjectName: 'proj3',
|
targetProjectName: 'proj3',
|
||||||
sourceProjectFile: 'libs/proj/package.json',
|
sourceProjectFile: 'libs/proj/package.json',
|
||||||
|
dependencyType: DependencyType.static,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,9 +1,11 @@
|
|||||||
import { ProjectGraph, ProjectGraphNodeRecords } from '../project-graph-models';
|
import { ProjectGraph, ProjectGraphNodeRecords } from '../project-graph-models';
|
||||||
import { defaultFileRead } from '../../file-utils';
|
import { defaultFileRead } from '../../file-utils';
|
||||||
import {
|
import {
|
||||||
|
DependencyType,
|
||||||
joinPathFragments,
|
joinPathFragments,
|
||||||
parseJson,
|
parseJson,
|
||||||
ProjectFileMap,
|
ProjectFileMap,
|
||||||
|
ProjectGraphBuilderExplicitDependency,
|
||||||
Workspace,
|
Workspace,
|
||||||
} from '@nrwl/devkit';
|
} from '@nrwl/devkit';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
@ -12,8 +14,8 @@ export function buildExplicitPackageJsonDependencies(
|
|||||||
workspace: Workspace,
|
workspace: Workspace,
|
||||||
graph: ProjectGraph,
|
graph: ProjectGraph,
|
||||||
filesToProcess: ProjectFileMap
|
filesToProcess: ProjectFileMap
|
||||||
) {
|
): ProjectGraphBuilderExplicitDependency[] {
|
||||||
const res = [] as any;
|
const res: ProjectGraphBuilderExplicitDependency[] = [];
|
||||||
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) => {
|
||||||
@ -55,7 +57,7 @@ function processPackageJson(
|
|||||||
sourceProject: string,
|
sourceProject: string,
|
||||||
fileName: string,
|
fileName: string,
|
||||||
graph: ProjectGraph,
|
graph: ProjectGraph,
|
||||||
collectedDeps: any[],
|
collectedDeps: ProjectGraphBuilderExplicitDependency[],
|
||||||
packageNameMap: { [packageName: string]: string }
|
packageNameMap: { [packageName: string]: string }
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
@ -68,12 +70,14 @@ function processPackageJson(
|
|||||||
sourceProjectName: sourceProject,
|
sourceProjectName: sourceProject,
|
||||||
targetProjectName: packageNameMap[d],
|
targetProjectName: packageNameMap[d],
|
||||||
sourceProjectFile: fileName,
|
sourceProjectFile: fileName,
|
||||||
|
dependencyType: DependencyType.static,
|
||||||
});
|
});
|
||||||
} else if (graph.externalNodes[`npm:${d}`]) {
|
} else if (graph.externalNodes[`npm:${d}`]) {
|
||||||
collectedDeps.push({
|
collectedDeps.push({
|
||||||
sourceProjectName: sourceProject,
|
sourceProjectName: sourceProject,
|
||||||
targetProjectName: `npm:${d}`,
|
targetProjectName: `npm:${d}`,
|
||||||
sourceProjectFile: fileName,
|
sourceProjectFile: fileName,
|
||||||
|
dependencyType: DependencyType.static,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import { vol } from 'memfs';
|
|||||||
import { ProjectGraphNode } from '../project-graph-models';
|
import { ProjectGraphNode } from '../project-graph-models';
|
||||||
import { buildExplicitTypeScriptDependencies } from './explicit-project-dependencies';
|
import { buildExplicitTypeScriptDependencies } from './explicit-project-dependencies';
|
||||||
import {
|
import {
|
||||||
|
DependencyType,
|
||||||
ProjectGraphBuilder,
|
ProjectGraphBuilder,
|
||||||
ProjectGraphProcessorContext,
|
ProjectGraphProcessorContext,
|
||||||
} from '@nrwl/devkit';
|
} from '@nrwl/devkit';
|
||||||
@ -201,21 +202,25 @@ describe('explicit project dependencies', () => {
|
|||||||
sourceProjectFile: 'libs/proj1234/index.ts',
|
sourceProjectFile: 'libs/proj1234/index.ts',
|
||||||
sourceProjectName: 'proj1234',
|
sourceProjectName: 'proj1234',
|
||||||
targetProjectName: 'proj1234-child',
|
targetProjectName: 'proj1234-child',
|
||||||
|
dependencyType: DependencyType.static,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
sourceProjectFile: 'libs/proj/index.ts',
|
sourceProjectFile: 'libs/proj/index.ts',
|
||||||
sourceProjectName: 'proj',
|
sourceProjectName: 'proj',
|
||||||
targetProjectName: 'proj2',
|
targetProjectName: 'proj2',
|
||||||
|
dependencyType: DependencyType.static,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
sourceProjectFile: 'libs/proj/index.ts',
|
sourceProjectFile: 'libs/proj/index.ts',
|
||||||
sourceProjectName: 'proj',
|
sourceProjectName: 'proj',
|
||||||
targetProjectName: 'proj3a',
|
targetProjectName: 'proj3a',
|
||||||
|
dependencyType: DependencyType.dynamic,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
sourceProjectFile: 'libs/proj/index.ts',
|
sourceProjectFile: 'libs/proj/index.ts',
|
||||||
sourceProjectName: 'proj',
|
sourceProjectName: 'proj',
|
||||||
targetProjectName: 'proj4ab',
|
targetProjectName: 'proj4ab',
|
||||||
|
dependencyType: DependencyType.dynamic,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -3,8 +3,7 @@ import { TypeScriptImportLocator } from './typescript-import-locator';
|
|||||||
import { TargetProjectLocator } from '../../target-project-locator';
|
import { TargetProjectLocator } from '../../target-project-locator';
|
||||||
import {
|
import {
|
||||||
ProjectFileMap,
|
ProjectFileMap,
|
||||||
ProjectGraphBuilder,
|
ProjectGraphBuilderExplicitDependency,
|
||||||
ProjectGraphProcessorContext,
|
|
||||||
Workspace,
|
Workspace,
|
||||||
} from '@nrwl/devkit';
|
} from '@nrwl/devkit';
|
||||||
|
|
||||||
@ -12,13 +11,13 @@ export function buildExplicitTypeScriptDependencies(
|
|||||||
workspace: Workspace,
|
workspace: Workspace,
|
||||||
graph: ProjectGraph,
|
graph: ProjectGraph,
|
||||||
filesToProcess: ProjectFileMap
|
filesToProcess: ProjectFileMap
|
||||||
) {
|
): ProjectGraphBuilderExplicitDependency[] {
|
||||||
const importLocator = new TypeScriptImportLocator();
|
const importLocator = new TypeScriptImportLocator();
|
||||||
const targetProjectLocator = new TargetProjectLocator(
|
const targetProjectLocator = new TargetProjectLocator(
|
||||||
graph.nodes,
|
graph.nodes,
|
||||||
graph.externalNodes
|
graph.externalNodes
|
||||||
);
|
);
|
||||||
const res = [] as any;
|
const res: ProjectGraphBuilderExplicitDependency[] = [];
|
||||||
Object.keys(filesToProcess).forEach((source) => {
|
Object.keys(filesToProcess).forEach((source) => {
|
||||||
Object.values(filesToProcess[source]).forEach((f) => {
|
Object.values(filesToProcess[source]).forEach((f) => {
|
||||||
importLocator.fromFile(
|
importLocator.fromFile(
|
||||||
@ -34,6 +33,7 @@ export function buildExplicitTypeScriptDependencies(
|
|||||||
sourceProjectName: source,
|
sourceProjectName: source,
|
||||||
targetProjectName: target,
|
targetProjectName: target,
|
||||||
sourceProjectFile: f.file,
|
sourceProjectFile: f.file,
|
||||||
|
dependencyType: type,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import { DependencyType } from '@nrwl/devkit';
|
|||||||
import { stripSourceCode } from '../../../utilities/strip-source-code';
|
import { stripSourceCode } from '../../../utilities/strip-source-code';
|
||||||
import { defaultFileRead } from '../../file-utils';
|
import { defaultFileRead } from '../../file-utils';
|
||||||
|
|
||||||
let tsModule: any;
|
let tsModule: typeof ts;
|
||||||
|
|
||||||
export class TypeScriptImportLocator {
|
export class TypeScriptImportLocator {
|
||||||
private readonly scanner: ts.Scanner;
|
private readonly scanner: ts.Scanner;
|
||||||
@ -46,7 +46,7 @@ export class TypeScriptImportLocator {
|
|||||||
|
|
||||||
fromNode(
|
fromNode(
|
||||||
filePath: string,
|
filePath: string,
|
||||||
node: any,
|
node: ts.Node,
|
||||||
visitor: (
|
visitor: (
|
||||||
importExpr: string,
|
importExpr: string,
|
||||||
filePath: string,
|
filePath: string,
|
||||||
@ -59,7 +59,15 @@ export class TypeScriptImportLocator {
|
|||||||
) {
|
) {
|
||||||
if (!this.ignoreStatement(node)) {
|
if (!this.ignoreStatement(node)) {
|
||||||
const imp = this.getStringLiteralValue(node.moduleSpecifier);
|
const imp = this.getStringLiteralValue(node.moduleSpecifier);
|
||||||
visitor(imp, filePath, DependencyType.static);
|
const isTypeOnly =
|
||||||
|
(tsModule.isImportDeclaration(node) &&
|
||||||
|
node.importClause?.isTypeOnly) ||
|
||||||
|
(tsModule.isExportDeclaration(node) && node.isTypeOnly);
|
||||||
|
visitor(
|
||||||
|
imp,
|
||||||
|
filePath,
|
||||||
|
isTypeOnly ? DependencyType.typeOnly : DependencyType.static
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return; // stop traversing downwards
|
return; // stop traversing downwards
|
||||||
}
|
}
|
||||||
|
|||||||
@ -72,6 +72,12 @@ describe('project graph', () => {
|
|||||||
projectType: 'library',
|
projectType: 'library',
|
||||||
targets: {},
|
targets: {},
|
||||||
},
|
},
|
||||||
|
'types-lib': {
|
||||||
|
root: 'libs/types-lib',
|
||||||
|
sourceRoot: 'libs/types-lib',
|
||||||
|
projectType: 'library',
|
||||||
|
targets: {},
|
||||||
|
},
|
||||||
api: {
|
api: {
|
||||||
root: 'apps/api/',
|
root: 'apps/api/',
|
||||||
sourceRoot: 'apps/api/src',
|
sourceRoot: 'apps/api/src',
|
||||||
@ -98,6 +104,7 @@ describe('project graph', () => {
|
|||||||
'@nrwl/shared-util-data': ['libs/shared/util/data/src/index.ts'],
|
'@nrwl/shared-util-data': ['libs/shared/util/data/src/index.ts'],
|
||||||
'@nrwl/ui': ['libs/ui/src/index.ts'],
|
'@nrwl/ui': ['libs/ui/src/index.ts'],
|
||||||
'@nrwl/lazy-lib': ['libs/lazy-lib/src/index.ts'],
|
'@nrwl/lazy-lib': ['libs/lazy-lib/src/index.ts'],
|
||||||
|
'@nrwl/types-lib': ['libs/types-lib/src/index.ts'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -108,6 +115,7 @@ describe('project graph', () => {
|
|||||||
'./apps/demo/src/index.ts': stripIndents`
|
'./apps/demo/src/index.ts': stripIndents`
|
||||||
import * as ui from '@nrwl/ui';
|
import * as ui from '@nrwl/ui';
|
||||||
import * as data from '@nrwl/shared-util-data;
|
import * as data from '@nrwl/shared-util-data;
|
||||||
|
import type { MyType } from '@nrwl/types-lib;
|
||||||
const s = { loadChildren: '@nrwl/lazy-lib#LAZY' }
|
const s = { loadChildren: '@nrwl/lazy-lib#LAZY' }
|
||||||
`,
|
`,
|
||||||
'./apps/demo-e2e/src/integration/app.spec.ts': stripIndents`
|
'./apps/demo-e2e/src/integration/app.spec.ts': stripIndents`
|
||||||
@ -126,6 +134,9 @@ describe('project graph', () => {
|
|||||||
'./libs/lazy-lib/src/index.ts': stripIndents`
|
'./libs/lazy-lib/src/index.ts': stripIndents`
|
||||||
export const LAZY = 'lazy lib';
|
export const LAZY = 'lazy lib';
|
||||||
`,
|
`,
|
||||||
|
'./libs/types-lib/src/index.ts': stripIndents`
|
||||||
|
export type MyType = {};
|
||||||
|
`,
|
||||||
'./package.json': JSON.stringify(packageJson),
|
'./package.json': JSON.stringify(packageJson),
|
||||||
'./nx.json': JSON.stringify(nxJson),
|
'./nx.json': JSON.stringify(nxJson),
|
||||||
'./workspace.json': JSON.stringify(workspaceJson),
|
'./workspace.json': JSON.stringify(workspaceJson),
|
||||||
@ -142,7 +153,9 @@ describe('project graph', () => {
|
|||||||
fail('Invalid tsconfigs should cause project graph to throw error');
|
fail('Invalid tsconfigs should cause project graph to throw error');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
expect(e.message).toMatchInlineSnapshot(
|
expect(e.message).toMatchInlineSnapshot(
|
||||||
`"InvalidSymbol in /root/tsconfig.base.json at position 247"`
|
`"InvalidSymbol in /root/tsconfig.base.json at position ${
|
||||||
|
JSON.stringify(tsConfigJson).length
|
||||||
|
}"`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -176,23 +189,35 @@ describe('project graph', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
expect(graph.dependencies).toEqual({
|
expect(graph.dependencies).toEqual({
|
||||||
api: [{ source: 'api', target: 'npm:express', type: 'static' }],
|
api: [
|
||||||
|
{ source: 'api', target: 'npm:express', type: DependencyType.static },
|
||||||
|
],
|
||||||
demo: [
|
demo: [
|
||||||
{ source: 'demo', target: 'api', type: 'implicit' },
|
{ source: 'demo', target: 'api', type: DependencyType.implicit },
|
||||||
{
|
{
|
||||||
source: 'demo',
|
source: 'demo',
|
||||||
target: 'ui',
|
target: 'ui',
|
||||||
type: 'static',
|
type: DependencyType.static,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
source: 'demo',
|
||||||
|
target: 'shared-util-data',
|
||||||
|
type: DependencyType.static,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
source: 'demo',
|
||||||
|
target: 'types-lib',
|
||||||
|
type: DependencyType.typeOnly,
|
||||||
},
|
},
|
||||||
{ source: 'demo', target: 'shared-util-data', type: 'static' },
|
|
||||||
{
|
{
|
||||||
source: 'demo',
|
source: 'demo',
|
||||||
target: 'lazy-lib',
|
target: 'lazy-lib',
|
||||||
type: 'static',
|
type: DependencyType.dynamic,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
'demo-e2e': [],
|
'demo-e2e': [],
|
||||||
'lazy-lib': [],
|
'lazy-lib': [],
|
||||||
|
'types-lib': [],
|
||||||
'shared-util': [
|
'shared-util': [
|
||||||
{ source: 'shared-util', target: 'npm:happy-nrwl', type: 'static' },
|
{ source: 'shared-util', target: 'npm:happy-nrwl', type: 'static' },
|
||||||
],
|
],
|
||||||
@ -202,7 +227,7 @@ describe('project graph', () => {
|
|||||||
{
|
{
|
||||||
source: 'ui',
|
source: 'ui',
|
||||||
target: 'lazy-lib',
|
target: 'lazy-lib',
|
||||||
type: 'static',
|
type: 'dynamic',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
@ -244,7 +269,7 @@ describe('project graph', () => {
|
|||||||
target: 'shared-util',
|
target: 'shared-util',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: DependencyType.static,
|
type: DependencyType.dynamic,
|
||||||
source: 'ui',
|
source: 'ui',
|
||||||
target: 'lazy-lib',
|
target: 'lazy-lib',
|
||||||
},
|
},
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import {
|
|||||||
ProjectFileMap,
|
ProjectFileMap,
|
||||||
ProjectGraph,
|
ProjectGraph,
|
||||||
ProjectGraphBuilder,
|
ProjectGraphBuilder,
|
||||||
|
ProjectGraphBuilderExplicitDependency,
|
||||||
ProjectGraphProcessorContext,
|
ProjectGraphProcessorContext,
|
||||||
readJsonFile,
|
readJsonFile,
|
||||||
WorkspaceJsonConfiguration,
|
WorkspaceJsonConfiguration,
|
||||||
@ -280,7 +281,8 @@ function buildExplicitDependenciesWithoutWorkers(
|
|||||||
builder.addExplicitDependency(
|
builder.addExplicitDependency(
|
||||||
r.sourceProjectName,
|
r.sourceProjectName,
|
||||||
r.sourceProjectFile,
|
r.sourceProjectFile,
|
||||||
r.targetProjectName
|
r.targetProjectName,
|
||||||
|
r.dependencyType
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -306,13 +308,16 @@ function buildExplicitDependenciesUsingWorkers(
|
|||||||
return new Promise((res, reject) => {
|
return new Promise((res, reject) => {
|
||||||
for (let w of workers) {
|
for (let w of workers) {
|
||||||
w.on('message', (explicitDependencies) => {
|
w.on('message', (explicitDependencies) => {
|
||||||
explicitDependencies.forEach((r) => {
|
explicitDependencies.forEach(
|
||||||
builder.addExplicitDependency(
|
(r: ProjectGraphBuilderExplicitDependency) => {
|
||||||
r.sourceProjectName,
|
builder.addExplicitDependency(
|
||||||
r.sourceProjectFile,
|
r.sourceProjectName,
|
||||||
r.targetProjectName
|
r.sourceProjectFile,
|
||||||
);
|
r.targetProjectName,
|
||||||
});
|
r.dependencyType
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
if (bins.length > 0) {
|
if (bins.length > 0) {
|
||||||
w.postMessage({ filesToProcess: bins.shift() });
|
w.postMessage({ filesToProcess: bins.shift() });
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1170,7 +1170,16 @@ Circular file chain:
|
|||||||
});
|
});
|
||||||
|
|
||||||
function createFile(f: string, deps?: string[]): FileData {
|
function createFile(f: string, deps?: string[]): FileData {
|
||||||
return { file: f, hash: '', ...(deps && { deps }) };
|
return {
|
||||||
|
file: f,
|
||||||
|
hash: '',
|
||||||
|
...(deps && {
|
||||||
|
deps: deps.map((dep) => ({
|
||||||
|
projectName: dep,
|
||||||
|
dependencyType: DependencyType.static,
|
||||||
|
})),
|
||||||
|
}),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function runRule(
|
function runRule(
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { PackageJson } from '@nrwl/tao/src/shared/package-json';
|
import { PackageJson } from '@nrwl/tao/src/shared/package-json';
|
||||||
import { ProjectGraph } from '../core/project-graph';
|
import { DependencyType, ProjectGraph } from '../core/project-graph';
|
||||||
import {
|
import {
|
||||||
getProjectNameFromDirPath,
|
getProjectNameFromDirPath,
|
||||||
getSourceDirOfDependentProjects,
|
getSourceDirOfDependentProjects,
|
||||||
@ -52,17 +52,17 @@ describe('project graph utils', () => {
|
|||||||
dependencies: {
|
dependencies: {
|
||||||
'demo-app': [
|
'demo-app': [
|
||||||
{
|
{
|
||||||
type: 'static',
|
type: DependencyType.static,
|
||||||
source: 'demo-app',
|
source: 'demo-app',
|
||||||
target: 'ui',
|
target: 'ui',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'static',
|
type: DependencyType.static,
|
||||||
source: 'demo-app',
|
source: 'demo-app',
|
||||||
target: 'npm:chalk',
|
target: 'npm:chalk',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'static',
|
type: DependencyType.static,
|
||||||
source: 'demo-app',
|
source: 'demo-app',
|
||||||
target: 'core',
|
target: 'core',
|
||||||
},
|
},
|
||||||
|
|||||||
@ -116,17 +116,19 @@ export function checkCircularPath(
|
|||||||
export function findFilesInCircularPath(
|
export function findFilesInCircularPath(
|
||||||
circularPath: ProjectGraphNode[]
|
circularPath: ProjectGraphNode[]
|
||||||
): Array<string[]> {
|
): Array<string[]> {
|
||||||
const filePathChain = [];
|
const filePathChain: string[][] = [];
|
||||||
|
|
||||||
for (let i = 0; i < circularPath.length - 1; i++) {
|
for (let i = 0; i < circularPath.length - 1; i++) {
|
||||||
const next = circularPath[i + 1].name;
|
const next = circularPath[i + 1].name;
|
||||||
const files: FileData[] = circularPath[i].data.files;
|
const files: Record<string, FileData> = circularPath[i].data.files;
|
||||||
filePathChain.push(
|
filePathChain.push(
|
||||||
Object.keys(files)
|
Object.keys(files)
|
||||||
.filter(
|
.filter(
|
||||||
(key) => files[key].deps && files[key].deps.indexOf(next) !== -1
|
(key) =>
|
||||||
|
files[key].deps &&
|
||||||
|
files[key].deps.some((dep) => dep.projectName === next)
|
||||||
)
|
)
|
||||||
.map((key) => files[key].file)
|
.map((key) => (files[key] as FileData).file)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -254,7 +254,7 @@ export function mapProjectGraphFiles<T>(
|
|||||||
projectGraph.nodes as Record<string, ProjectGraphProjectNode>
|
projectGraph.nodes as Record<string, ProjectGraphProjectNode>
|
||||||
).forEach(([name, node]) => {
|
).forEach(([name, node]) => {
|
||||||
const files: Record<string, FileData> = {};
|
const files: Record<string, FileData> = {};
|
||||||
node.data.files.forEach(({ file, hash, deps }) => {
|
node.data.files.forEach(({ file, hash, deps }: FileData) => {
|
||||||
files[removeExt(file)] = { file, hash, ...(deps && { deps }) };
|
files[removeExt(file)] = { file, hash, ...(deps && { deps }) };
|
||||||
});
|
});
|
||||||
const data = { ...node.data, files };
|
const data = { ...node.data, files };
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user