diff --git a/docs/shared/reference/project-configuration.md b/docs/shared/reference/project-configuration.md index 7c9806e70ab58..5ba16a9bc71fb 100644 --- a/docs/shared/reference/project-configuration.md +++ b/docs/shared/reference/project-configuration.md @@ -276,6 +276,9 @@ result in `mylib`'s dependencies being built as well. You can also express the same configuration using: +{% tabs %} +{% tab label="Version < 16" %} + ```json "build": { "dependsOn": [{ "projects": "dependencies", "target": "build" }] @@ -285,8 +288,26 @@ You can also express the same configuration using: } ``` +{% /tab %} +{% tab label="Version 16+" %} + +```json +"build": { + "dependsOn": [{ "projects": "{dependencies}", "target": "build" }] +}, +"test": { + "dependsOn": [{ "projects": "{self}", "target": "build" }] +} +``` + +{% /tab %} +{% /tabs %} + With the expanded syntax, you also have a third option available to configure how to handle the params passed to the target. You can either forward them or you can ignore them (default). +{% tabs %} +{% tab label="Version < 16" %} + ```json "build": { // forward params passed to this target to the dependency targets @@ -302,8 +323,32 @@ With the expanded syntax, you also have a third option available to configure ho } ``` +{% /tab %} +{% tab label="Version 16+" %} + +```json +"build": { + // forward params passed to this target to the dependency targets + "dependsOn": [{ "projects": "{dependencies}", "target": "build", "params": "forward" }] +}, +"test": { + // ignore params passed to this target, won't be forwarded to the dependency targets + "dependsOn": [{ "projects": "{dependencies}", "target": "build", "params": "ignore" }] +} +"lint": { + // ignore params passed to this target, won't be forwarded to the dependency targets + "dependsOn": [{ "projects": "{dependencies}", "target": "build" }] +} +``` + +{% /tab %} +{% /tabs %} + Obviously this also works when defining a relation for the target of the project itself using `"projects": "self"`: +{% tabs %} +{% tab label="Version < 16" %} + ```json "build": { // forward params passed to this target to the project target @@ -311,6 +356,28 @@ Obviously this also works when defining a relation for the target of the project } ``` +{% /tab %} +{% tab label="Version 16+" %} + +```json +"build": { + // forward params passed to this target to the project target + "dependsOn": [{ "projects": "{self}", "target": "pre-build", "params": "forward" }] +} +``` + +{% /tab %} +{% /tabs %} + +Additionally, when using the expanded object syntax, you can specify individual projects in version 16 or greater. + +```json +"build": { + // Run is-even:pre-build and is-odd:pre-build before this target + "dependsOn": [{ "projects": ["is-even", "is-odd"], "target": "pre-build" }] +} +``` + This configuration is usually not needed. Nx comes with reasonable defaults (imported in `nx.json`) which implement the configuration above. diff --git a/packages/nx/migrations.json b/packages/nx/migrations.json index d944ff976f5a1..3c4178b0a9d42 100644 --- a/packages/nx/migrations.json +++ b/packages/nx/migrations.json @@ -59,6 +59,12 @@ "version": "16.0.0-beta.0", "description": "Remove @nrwl/cli.", "implementation": "./src/migrations/update-16-0-0/remove-nrwl-cli" + }, + "16.0.0-tokens-for-depends-on": { + "cli": "nx", + "version": "16.0.0-beta.0", + "description": "Replace `dependsOn.projects` with {self} or {dependencies} tokens so that it matches the new expected formatting.", + "implementation": "./src/migrations/update-16-0-0/update-depends-on-to-tokens" } } } diff --git a/packages/nx/schemas/nx-schema.json b/packages/nx/schemas/nx-schema.json index 2e774f2cc5e77..f852c44be585f 100644 --- a/packages/nx/schemas/nx-schema.json +++ b/packages/nx/schemas/nx-schema.json @@ -247,9 +247,19 @@ "type": "object", "properties": { "projects": { - "type": "string", - "description": "The projects that the targets belong to.", - "enum": ["self", "dependencies"] + "oneOf": [ + { + "type": "string", + "description": "{self}, {dependencies}, or a project name." + }, + { + "type": "array", + "description": "An array of project specifiers: {self}, {dependencies}, or a project name.", + "items": { + "type": "string" + } + } + ] }, "target": { "type": "string", diff --git a/packages/nx/schemas/project-schema.json b/packages/nx/schemas/project-schema.json index c57b50dd14de6..4c8cdc862c609 100644 --- a/packages/nx/schemas/project-schema.json +++ b/packages/nx/schemas/project-schema.json @@ -55,9 +55,19 @@ "type": "object", "properties": { "projects": { - "type": "string", - "description": "The projects that the targets belong to.", - "enum": ["self", "dependencies"] + "oneOf": [ + { + "type": "string", + "description": "{self}, {dependencies}, or a project name." + }, + { + "type": "array", + "description": "An array of project specifiers: {self}, {dependencies}, or a project name.", + "items": { + "type": "string" + } + } + ] }, "target": { "type": "string", diff --git a/packages/nx/schemas/workspace-schema.json b/packages/nx/schemas/workspace-schema.json index 24a5a89ce4d1c..df2cc3d6b7eb6 100644 --- a/packages/nx/schemas/workspace-schema.json +++ b/packages/nx/schemas/workspace-schema.json @@ -65,9 +65,19 @@ "type": "object", "properties": { "projects": { - "type": "string", - "description": "The projects that the targets belong to.", - "enum": ["self", "dependencies"] + "oneOf": [ + { + "type": "string", + "description": "{self}, {dependencies}, or a project name." + }, + { + "type": "array", + "description": "An array of project specifiers: {self}, {dependencies}, or a project name.", + "items": { + "type": "string" + } + } + ] }, "target": { "type": "string", diff --git a/packages/nx/src/config/workspace-json-project-json.ts b/packages/nx/src/config/workspace-json-project-json.ts index 431a3238fb825..2212dec313b79 100644 --- a/packages/nx/src/config/workspace-json-project-json.ts +++ b/packages/nx/src/config/workspace-json-project-json.ts @@ -102,12 +102,15 @@ export interface ProjectConfiguration { export interface TargetDependencyConfig { /** - * This the projects that the targets belong to + * A list of projects that have `target`. Supports project names or two special values: * - * 'self': This target depends on another target of the same project - * 'deps': This target depends on targets of the projects of it's deps. + * - '{self}': This target depends on another target of the same project + * - '{dependencies}': This target depends on targets of the projects of it's deps. + * + * The special values {self}/{dependencies} should be preferred - they prevent cases where a project + * that needs to be built is missed. */ - projects: 'self' | 'dependencies'; + projects: string[] | string; /** * The name of the target diff --git a/packages/nx/src/migrations/update-16-0-0/update-depends-on-to-tokens.spec.ts b/packages/nx/src/migrations/update-16-0-0/update-depends-on-to-tokens.spec.ts new file mode 100644 index 0000000000000..86c66a9dbd3c2 --- /dev/null +++ b/packages/nx/src/migrations/update-16-0-0/update-depends-on-to-tokens.spec.ts @@ -0,0 +1,104 @@ +import { + addProjectConfiguration, + getProjects, + readNxJson, + readProjectConfiguration, +} from '../../generators/utils/project-configuration'; +import { Tree } from '../../generators/tree'; + +import update from './update-depends-on-to-tokens'; +import { updateJson, writeJson } from 'nx/src/devkit-exports'; +import { createTreeWithEmptyWorkspace } from '../../generators/testing-utils/create-tree-with-empty-workspace'; + +describe('update-depends-on-to-tokens', () => { + it('should update nx.json', async () => { + const tree = createTreeWithEmptyWorkspace(); + updateJson(tree, 'nx.json', (json) => { + json.targetDefaults = { + build: { + dependsOn: [ + { + projects: 'self', + }, + ], + }, + test: { + dependsOn: [ + { + projects: 'dependencies', + }, + ], + }, + other: { + dependsOn: ['^deps'], + }, + }; + return json; + }); + await update(tree); + const nxJson = readNxJson(tree); + const build = nxJson.targetDefaults.build.dependsOn[0] as any; + const test = nxJson.targetDefaults.test.dependsOn[0] as any; + expect(build.projects).toEqual('{self}'); + expect(test.projects).toEqual('{dependencies}'); + expect(nxJson.targetDefaults.other.dependsOn).toEqual(['^deps']); + }); + + it('should update project configurations', async () => { + const tree = createTreeWithEmptyWorkspace(); + addProjectConfiguration(tree, 'proj1', { + root: 'proj1', + targets: { + build: { + dependsOn: [ + { + projects: 'self', + target: 'build', + }, + ], + }, + test: { + dependsOn: [ + { + projects: 'dependencies', + target: 'test', + }, + ], + }, + other: { + dependsOn: ['^deps'], + }, + }, + }); + await update(tree); + const project = readProjectConfiguration(tree, 'proj1'); + const build = project.targets.build.dependsOn[0] as any; + const test = project.targets.test.dependsOn[0] as any; + expect(build.projects).toEqual('{self}'); + expect(test.projects).toEqual('{dependencies}'); + expect(project.targets.other.dependsOn).toEqual(['^deps']); + }); + + it('should not throw on nulls', async () => { + const tree = createTreeWithEmptyWorkspace(); + addProjectConfiguration(tree, 'proj1', { + root: 'proj1', + }); + addProjectConfiguration(tree, 'proj2', { + root: 'proj2', + targets: { + build: {}, + }, + }); + writeJson(tree, 'nx.json', {}); + let promise = update(tree); + await expect(promise).resolves.toBeUndefined(); + writeJson(tree, 'nx.json', { + targetDefaults: { + build: {}, + }, + }); + promise = update(tree); + await expect(promise).resolves.toBeUndefined(); + }); +}); diff --git a/packages/nx/src/migrations/update-16-0-0/update-depends-on-to-tokens.ts b/packages/nx/src/migrations/update-16-0-0/update-depends-on-to-tokens.ts new file mode 100644 index 0000000000000..8c68b5289de23 --- /dev/null +++ b/packages/nx/src/migrations/update-16-0-0/update-depends-on-to-tokens.ts @@ -0,0 +1,56 @@ +import { + getProjects, + readNxJson, + updateNxJson, + updateProjectConfiguration, +} from '../../generators/utils/project-configuration'; +import { Tree } from '../../generators/tree'; + +export default async function (tree: Tree) { + updateDependsOnInsideNxJson(tree); + + const projectsConfigurations = getProjects(tree); + for (const [projectName, projectConfiguration] of projectsConfigurations) { + let projectChanged = false; + for (const [targetName, targetConfiguration] of Object.entries( + projectConfiguration.targets ?? {} + )) { + for (const dependency of targetConfiguration.dependsOn ?? []) { + if (typeof dependency !== 'string') { + if (dependency.projects === 'self') { + dependency.projects = '{self}'; + projectChanged = true; + } else if (dependency.projects === 'dependencies') { + dependency.projects = '{dependencies}'; + projectChanged = true; + } + } + } + } + if (projectChanged) { + updateProjectConfiguration(tree, projectName, projectConfiguration); + } + } +} +function updateDependsOnInsideNxJson(tree: Tree) { + const nxJson = readNxJson(tree); + let nxJsonChanged = false; + for (const [target, defaults] of Object.entries( + nxJson?.targetDefaults ?? {} + )) { + for (const dependency of defaults.dependsOn ?? []) { + if (typeof dependency !== 'string') { + if (dependency.projects === 'self') { + dependency.projects = '{self}'; + nxJsonChanged = true; + } else if (dependency.projects === 'dependencies') { + dependency.projects = '{dependencies}'; + nxJsonChanged = true; + } + } + } + } + if (nxJsonChanged) { + updateNxJson(tree, nxJson); + } +} diff --git a/packages/nx/src/tasks-runner/create-task-graph.spec.ts b/packages/nx/src/tasks-runner/create-task-graph.spec.ts index 584baeaaeaabf..992dd1221b51f 100644 --- a/packages/nx/src/tasks-runner/create-task-graph.spec.ts +++ b/packages/nx/src/tasks-runner/create-task-graph.spec.ts @@ -17,17 +17,24 @@ describe('createTaskGraph', () => { prebuild: { executor: 'nx:run-commands', }, + prebuild2: { + executor: 'nx:run-commands', + }, build: { executor: 'nx:run-commands', dependsOn: [ { - projects: 'dependencies', + projects: '{dependencies}', target: 'build', }, { - projects: 'self', + projects: '{self}', target: 'prebuild', }, + { + projects: 'app1', + target: 'prebuild2', + }, ], }, test: { @@ -166,7 +173,7 @@ describe('createTaskGraph', () => { }, dependsOn: [ { - projects: 'dependencies', + projects: '{dependencies}', target: 'build', }, ], @@ -189,7 +196,7 @@ describe('createTaskGraph', () => { defaultConfiguration: 'libDefault', dependsOn: [ { - projects: 'dependencies', + projects: '{dependencies}', target: 'build', }, ], @@ -330,7 +337,7 @@ describe('createTaskGraph', () => { executor: 'my-executor', dependsOn: [ { - projects: 'dependencies', + projects: '{dependencies}', target: 'build', }, ], @@ -501,11 +508,11 @@ describe('createTaskGraph', () => { executor: 'nx:run-commands', dependsOn: [ { - projects: 'dependencies', + projects: '{dependencies}', target: 'build', params: 'forward', }, - { projects: 'self', target: 'prebuild', params: 'forward' }, + { projects: '{self}', target: 'prebuild', params: 'forward' }, ], }, test: { @@ -528,7 +535,7 @@ describe('createTaskGraph', () => { executor: 'nx:run-commands', dependsOn: [ { - projects: 'dependencies', + projects: '{dependencies}', target: 'build', params: 'ignore', }, @@ -640,7 +647,7 @@ describe('createTaskGraph', () => { ); // prebuild should also be in here expect(taskGraph).toEqual({ - roots: ['lib1:build', 'app1:prebuild'], + roots: ['lib1:build', 'app1:prebuild', 'app1:prebuild2'], tasks: { 'app1:build': { id: 'app1:build', @@ -664,6 +671,17 @@ describe('createTaskGraph', () => { }, projectRoot: 'app1-root', }, + 'app1:prebuild2': { + id: 'app1:prebuild2', + target: { + project: 'app1', + target: 'prebuild2', + }, + overrides: { + __overrides_unparsed__: [], + }, + projectRoot: 'app1-root', + }, 'lib1:build': { id: 'lib1:build', target: { @@ -677,8 +695,9 @@ describe('createTaskGraph', () => { }, }, dependencies: { - 'app1:build': ['lib1:build', 'app1:prebuild'], + 'app1:build': ['lib1:build', 'app1:prebuild', 'app1:prebuild2'], 'app1:prebuild': [], + 'app1:prebuild2': [], 'lib1:build': [], }, }); @@ -697,7 +716,7 @@ describe('createTaskGraph', () => { ); // prebuild should also be in here expect(taskGraph).toEqual({ - roots: ['app1:prebuild', 'lib1:build'], + roots: ['app1:prebuild', 'lib1:build', 'app1:prebuild2'], tasks: { 'app1:build': { id: 'app1:build', @@ -721,6 +740,17 @@ describe('createTaskGraph', () => { }, projectRoot: 'app1-root', }, + 'app1:prebuild2': { + id: 'app1:prebuild2', + target: { + project: 'app1', + target: 'prebuild2', + }, + overrides: { + __overrides_unparsed__: [], + }, + projectRoot: 'app1-root', + }, 'lib1:build': { id: 'lib1:build', target: { @@ -734,8 +764,9 @@ describe('createTaskGraph', () => { }, }, dependencies: { - 'app1:build': ['lib1:build', 'app1:prebuild'], + 'app1:build': ['lib1:build', 'app1:prebuild', 'app1:prebuild2'], 'app1:prebuild': [], + 'app1:prebuild2': [], 'lib1:build': [], }, }); @@ -813,7 +844,7 @@ describe('createTaskGraph', () => { { build: [ { - projects: 'dependencies', + projects: '{dependencies}', target: 'build', }, ], @@ -974,9 +1005,9 @@ describe('createTaskGraph', () => { { build: ['^build'], apply: [ - { projects: 'dependencies', target: 'build' }, + { projects: '{dependencies}', target: 'build' }, { - projects: 'dependencies', + projects: '{dependencies}', target: 'apply', params: 'forward', }, @@ -1052,11 +1083,11 @@ describe('createTaskGraph', () => { targets: { build: { executor: 'nx:run-commands', - dependsOn: [{ target: 'test', projects: 'self' }], + dependsOn: [{ target: 'test', projects: '{self}' }], }, test: { executor: 'nx:run-commands', - dependsOn: [{ target: 'build', projects: 'self' }], + dependsOn: [{ target: 'build', projects: '{self}' }], }, }, }, @@ -1161,7 +1192,7 @@ describe('createTaskGraph', () => { const taskGraph = createTaskGraph( projectGraph, { - build: [{ target: 'build', projects: 'dependencies' }], + build: [{ target: 'build', projects: '{dependencies}' }], }, ['app1'], ['build'], @@ -1252,7 +1283,7 @@ describe('createTaskGraph', () => { const taskGraph = createTaskGraph( projectGraph, { - build: [{ target: 'build', projects: 'dependencies' }], + build: [{ target: 'build', projects: '{dependencies}' }], }, ['app1'], ['build'], @@ -1307,8 +1338,8 @@ describe('createTaskGraph', () => { build: { executor: 'nx:run-commands', dependsOn: [ - { target: 'prebuild', projects: 'self' }, - { target: 'build', projects: 'dependencies' }, + { target: 'prebuild', projects: '{self}' }, + { target: 'build', projects: '{dependencies}' }, ], }, prebuild: { diff --git a/packages/nx/src/tasks-runner/create-task-graph.ts b/packages/nx/src/tasks-runner/create-task-graph.ts index 06f269be5724e..ff31a05658d72 100644 --- a/packages/nx/src/tasks-runner/create-task-graph.ts +++ b/packages/nx/src/tasks-runner/create-task-graph.ts @@ -6,6 +6,7 @@ import { } from '../utils/project-graph-utils'; import { Task, TaskGraph } from '../config/task-graph'; import { TargetDependencies } from '../config/nx-json'; +import { TargetDependencyConfig } from '../devkit-exports'; export class ProcessTasks { private readonly seen = new Set(); @@ -104,92 +105,150 @@ export class ProcessTasks { dependencyConfig.params === 'forward' ? overrides : { __overrides_unparsed__: [] }; + const targetProjectSpecifiers = + typeof dependencyConfig.projects === 'string' + ? [dependencyConfig.projects] + : dependencyConfig.projects; + for (const projectSpecifier of targetProjectSpecifiers) { + // Lerna uses `dependencies` in `prepNxOptions`, so we need to maintain + // support for it until lerna can be updated to use the new tokens. + // TODO(@agentender): Remove this part in v17 + if ( + projectSpecifier === '{dependencies}' || + (projectSpecifier === 'dependencies' && + !this.projectGraph.nodes[projectSpecifier]) + ) { + this.processTasksForDependencies( + projectUsedToDeriveDependencies, + dependencyConfig, + configuration, + task, + taskOverrides, + overrides + ); + } else { + // Since we need to maintain support for dependencies, it is more coherent + // that we also support self. + // TODO(@agentender): Remove this part in v17 + const projectName = + projectSpecifier === '{self}' || + (projectSpecifier === 'self' && + !this.projectGraph.nodes[projectSpecifier]) + ? task.target.project + : projectSpecifier; + + this.processTasksForSingleProject( + task, + projectName, + dependencyConfig, + configuration, + taskOverrides, + overrides + ); + } + } + } + } - if (dependencyConfig.projects === 'dependencies') { - for (const dep of this.projectGraph.dependencies[ - projectUsedToDeriveDependencies - ]) { - const depProject = this.projectGraph.nodes[ - dep.target - ] as ProjectGraphProjectNode; + private processTasksForSingleProject( + task: Task, + projectName: string, + dependencyConfig: TargetDependencyConfig, + configuration: string, + taskOverrides: Object | { __overrides_unparsed__: any[] }, + overrides: Object + ) { + const selfProject = this.projectGraph.nodes[ + projectName + ] as ProjectGraphProjectNode; + + if (projectHasTarget(selfProject, dependencyConfig.target)) { + const resolvedConfiguration = this.resolveConfiguration( + selfProject, + dependencyConfig.target, + configuration + ); + const selfTaskId = this.getId( + selfProject.name, + dependencyConfig.target, + resolvedConfiguration + ); + if (task.id !== selfTaskId) { + this.dependencies[task.id].push(selfTaskId); + } + if (!this.tasks[selfTaskId]) { + const newTask = this.createTask( + selfTaskId, + selfProject, + dependencyConfig.target, + resolvedConfiguration, + taskOverrides + ); + this.tasks[selfTaskId] = newTask; + this.dependencies[selfTaskId] = []; + this.processTask( + newTask, + newTask.target.project, + configuration, + overrides + ); + } + } + } - // this is to handle external dependencies - if (!depProject) continue; + private processTasksForDependencies( + projectUsedToDeriveDependencies: string, + dependencyConfig: TargetDependencyConfig, + configuration: string, + task: Task, + taskOverrides: Object | { __overrides_unparsed__: any[] }, + overrides: Object + ) { + for (const dep of this.projectGraph.dependencies[ + projectUsedToDeriveDependencies + ]) { + const depProject = this.projectGraph.nodes[ + dep.target + ] as ProjectGraphProjectNode; - if (projectHasTarget(depProject, dependencyConfig.target)) { - const resolvedConfiguration = this.resolveConfiguration( - depProject, - dependencyConfig.target, - configuration - ); - const depTargetId = this.getId( - depProject.name, - dependencyConfig.target, - resolvedConfiguration - ); + // this is to handle external dependencies + if (!depProject) continue; - if (task.id !== depTargetId) { - this.dependencies[task.id].push(depTargetId); - } - if (!this.tasks[depTargetId]) { - const newTask = this.createTask( - depTargetId, - depProject, - dependencyConfig.target, - resolvedConfiguration, - taskOverrides - ); - this.tasks[depTargetId] = newTask; - this.dependencies[depTargetId] = []; + if (projectHasTarget(depProject, dependencyConfig.target)) { + const resolvedConfiguration = this.resolveConfiguration( + depProject, + dependencyConfig.target, + configuration + ); + const depTargetId = this.getId( + depProject.name, + dependencyConfig.target, + resolvedConfiguration + ); - this.processTask( - newTask, - newTask.target.project, - configuration, - overrides - ); - } - } else { - this.processTask(task, depProject.name, configuration, overrides); - } + if (task.id !== depTargetId) { + this.dependencies[task.id].push(depTargetId); } - } else { - const selfProject = this.projectGraph.nodes[ - task.target.project - ] as ProjectGraphProjectNode; - - if (projectHasTarget(selfProject, dependencyConfig.target)) { - const resolvedConfiguration = this.resolveConfiguration( - selfProject, + if (!this.tasks[depTargetId]) { + const newTask = this.createTask( + depTargetId, + depProject, dependencyConfig.target, - configuration + resolvedConfiguration, + taskOverrides ); - const selfTaskId = this.getId( - selfProject.name, - dependencyConfig.target, - resolvedConfiguration + this.tasks[depTargetId] = newTask; + this.dependencies[depTargetId] = []; + + this.processTask( + newTask, + newTask.target.project, + configuration, + overrides ); - if (task.id !== selfTaskId) { - this.dependencies[task.id].push(selfTaskId); - } - if (!this.tasks[selfTaskId]) { - const newTask = this.createTask( - selfTaskId, - selfProject, - dependencyConfig.target, - resolvedConfiguration, - taskOverrides - ); - this.tasks[selfTaskId] = newTask; - this.dependencies[selfTaskId] = []; - this.processTask( - newTask, - newTask.target.project, - configuration, - overrides - ); - } } + } else { + this.processTask(task, depProject.name, configuration, overrides); } } } diff --git a/packages/nx/src/tasks-runner/utils.ts b/packages/nx/src/tasks-runner/utils.ts index 0ebd2714c49b1..0f98ff049fc77 100644 --- a/packages/nx/src/tasks-runner/utils.ts +++ b/packages/nx/src/tasks-runner/utils.ts @@ -32,17 +32,26 @@ export function getDependencyConfigs( [] ); for (const dependencyConfig of dependencyConfigs) { - if ( - dependencyConfig.projects !== 'dependencies' && - dependencyConfig.projects !== 'self' - ) { - output.error({ - title: `dependsOn is improperly configured for ${project}:${target}`, - bodyLines: [ - `dependsOn.projects is "${dependencyConfig.projects}" but should be "self" or "dependencies"`, - ], - }); - process.exit(1); + const specifiers = + typeof dependencyConfig.projects === 'string' + ? [dependencyConfig.projects] + : dependencyConfig.projects; + for (const specifier of specifiers) { + if ( + !(specifier in projectGraph.nodes) && + // Todo(@agentender): Remove the non-token forms of these for v17 + !['{self}', '{dependencies}', 'self', 'dependencies'].includes( + specifier + ) + ) { + output.error({ + title: `dependsOn is improperly configured for ${project}:${target}`, + bodyLines: [ + `${specifier} in dependsOn.projects is invalid. It should be "{self}", "{dependencies}", or a project name.`, + ], + }); + process.exit(1); + } } } return dependencyConfigs; @@ -54,9 +63,9 @@ function expandDependencyConfigSyntaxSugar( return deps.map((d) => { if (typeof d === 'string') { if (d.startsWith('^')) { - return { projects: 'dependencies', target: d.substring(1) }; + return { projects: '{dependencies}', target: d.substring(1) }; } else { - return { projects: 'self', target: d }; + return { projects: '{self}', target: d }; } } else { return d;