Skip to content

Commit

Permalink
feat(core): support specific project dependency in dependsOn with str…
Browse files Browse the repository at this point in the history
…ing syntax (#16674)
  • Loading branch information
AgentEnder authored May 2, 2023
1 parent 4be6f74 commit e164d50
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 18 deletions.
54 changes: 54 additions & 0 deletions packages/nx/src/tasks-runner/utils.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
expandDependencyConfigSyntaxSugar,
getOutputsForTargetAndConfiguration,
transformLegacyOutputs,
validateOutputs,
Expand Down Expand Up @@ -397,4 +398,57 @@ describe('utils', () => {
expect(result).toEqual(['{projectRoot}/dist']);
}
});

describe('expandDependencyConfigSyntaxSugar', () => {
it('should expand syntax for simple target names', () => {
const result = expandDependencyConfigSyntaxSugar('build', {
dependencies: {},
nodes: {},
});
expect(result).toEqual({
target: 'build',
});
});

it('should expand syntax for simple target names targetting dependencies', () => {
const result = expandDependencyConfigSyntaxSugar('^build', {
dependencies: {},
nodes: {},
});
expect(result).toEqual({
target: 'build',
dependencies: true,
});
});

it('should expand syntax for strings like project:target if project is a valid project', () => {
const result = expandDependencyConfigSyntaxSugar('project:build', {
dependencies: {},
nodes: {
project: {
name: 'project',
type: 'app',
data: {
root: 'libs/project',
files: [],
},
},
},
});
expect(result).toEqual({
target: 'build',
projects: ['project'],
});
});

it('should expand syntax for strings like target:with:colons', () => {
const result = expandDependencyConfigSyntaxSugar('target:with:colons', {
dependencies: {},
nodes: {},
});
expect(result).toEqual({
target: 'target:with:colons',
});
});
});
});
51 changes: 34 additions & 17 deletions packages/nx/src/tasks-runner/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { NxJsonConfiguration } from '../config/nx-json';
import { joinPathFragments } from '../utils/path';
import { isRelativePath } from '../utils/fileutils';
import { serializeOverridesIntoCommandLine } from '../utils/serialize-overrides-into-command-line';
import { splitByColons, splitTarget } from '../utils/split-target';

export function getCommandAsString(execCommand: string, task: Task) {
const args = getPrintableCommandArgsForTask(task);
Expand All @@ -26,10 +27,14 @@ export function getDependencyConfigs(
defaultDependencyConfigs: Record<string, (TargetDependencyConfig | string)[]>,
projectGraph: ProjectGraph
): TargetDependencyConfig[] | undefined {
const dependencyConfigs = expandDependencyConfigSyntaxSugar(
const dependencyConfigs = (
projectGraph.nodes[project].data?.targets[target]?.dependsOn ??
defaultDependencyConfigs[target] ??
[]
defaultDependencyConfigs[target] ??
[]
).map((config) =>
typeof config === 'string'
? expandDependencyConfigSyntaxSugar(config, projectGraph)
: config
);
for (const dependencyConfig of dependencyConfigs) {
const specifiers =
Expand Down Expand Up @@ -64,20 +69,32 @@ export function getDependencyConfigs(
return dependencyConfigs;
}

function expandDependencyConfigSyntaxSugar(
deps: (TargetDependencyConfig | string)[]
): TargetDependencyConfig[] {
return deps.map((d) => {
if (typeof d === 'string') {
if (d.startsWith('^')) {
return { dependencies: true, target: d.substring(1) };
} else {
return { target: d };
}
} else {
return d;
}
});
export function expandDependencyConfigSyntaxSugar(
dependencyConfigString: string,
graph: ProjectGraph
): TargetDependencyConfig {
const [dependencies, targetString] = dependencyConfigString.startsWith('^')
? [true, dependencyConfigString.substring(1)]
: [false, dependencyConfigString];

// Support for `project:target` syntax doesn't make sense for
// dependencies, so we only support `target` syntax for dependencies.
if (dependencies) {
return {
target: targetString,
dependencies: true,
};
}

// Support for both `project:target` and `target:with:colons` syntax
const [maybeProject, ...segments] = splitByColons(targetString);
return {
// Only the first segment could be a project. If it is, the rest is a target.
// If its not, then the whole targetString was a target with colons in its name.
target: maybeProject in graph.nodes ? segments.join(':') : targetString,
// If the first segment is a project, then we have a specific project. Otherwise, we don't.
projects: maybeProject in graph.nodes ? [maybeProject] : undefined,
};
}

export function getOutputs(
Expand Down
2 changes: 1 addition & 1 deletion packages/nx/src/utils/split-target.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ function groupJointSegments(segments: string[], validTargetNames: Set<string>) {
return segments;
}

function splitByColons(s: string) {
export function splitByColons(s: string) {
const parts = [] as string[];
let currentPart = '';
for (let i = 0; i < s.length; ++i) {
Expand Down

1 comment on commit e164d50

@vercel
Copy link

@vercel vercel bot commented on e164d50 May 2, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

nx-dev – ./

nx-dev-git-master-nrwl.vercel.app
nx-dev-nrwl.vercel.app
nx-five.vercel.app
nx.dev

Please sign in to comment.