Skip to content

Commit

Permalink
fix(core): automatically add root to the project.json projects (#9977)
Browse files Browse the repository at this point in the history
* fix(core): automatically add root to the project.json projects

* chore(core): move project-configuration generator utils to nx package

* fix(core): add migrations to remove root
  • Loading branch information
FrozenPandaz committed Apr 28, 2022
1 parent c3d30a4 commit 5e23c07
Show file tree
Hide file tree
Showing 41 changed files with 339 additions and 176 deletions.
3 changes: 0 additions & 3 deletions e2e/angular-core/src/ng-add.test.ts
Expand Up @@ -182,7 +182,6 @@ describe('convert Angular CLI workspace to an Nx workspace', () => {

// check project configuration
const projectConfig = readJson(`apps/${project}/project.json`);
expect(projectConfig.root).toEqual(`apps/${project}`);
expect(projectConfig.sourceRoot).toEqual(`apps/${project}/src`);
expect(projectConfig.targets.build).toEqual({
executor: '@angular-devkit/build-angular:browser',
Expand Down Expand Up @@ -259,7 +258,6 @@ describe('convert Angular CLI workspace to an Nx workspace', () => {

// check e2e project config
const e2eProjectConfig = readJson(`apps/${project}-e2e/project.json`);
expect(e2eProjectConfig.root).toEqual(`apps/${project}-e2e`);
expect(e2eProjectConfig.targets.e2e).toEqual({
executor: '@angular-devkit/build-angular:protractor',
options: {
Expand Down Expand Up @@ -356,7 +354,6 @@ describe('convert Angular CLI workspace to an Nx workspace', () => {

// check e2e project config
const e2eProjectConfig = readJson(`apps/${project}-e2e/project.json`);
expect(e2eProjectConfig.root).toEqual(`apps/${e2eProject}`);
expect(e2eProjectConfig.targets['cypress-run']).toEqual({
executor: '@nrwl/cypress:cypress',
options: {
Expand Down
2 changes: 1 addition & 1 deletion e2e/nx-plugin/src/nx-plugin.test.ts
Expand Up @@ -282,7 +282,7 @@ describe('Nx Plugin', () => {
checkFilesExist(`libs/subdir/${plugin}/package.json`);
const pluginProject = readProjectConfig(`subdir-${plugin}`);
const pluginE2EProject = readProjectConfig(`subdir-${plugin}-e2e`);
expect(pluginProject.root).toBe(`libs/subdir/${plugin}`);
expect(pluginProject.targets).toBeDefined();
expect(pluginE2EProject).toBeTruthy();
}, 90000);
});
Expand Down
3 changes: 0 additions & 3 deletions e2e/workspace-core/src/aux-commands.test.ts
Expand Up @@ -318,7 +318,6 @@ describe('move project', () => {
expect(workspaceJson.projects[`${lib1}-data-access`]).toBeUndefined();
const project = readProjectConfig(newName);
expect(project).toBeTruthy();
expect(project.root).toBe(newPath);
expect(project.sourceRoot).toBe(`${newPath}/src`);
expect(project.targets.lint.options.lintFilePatterns).toEqual([
`libs/shared/${lib1}/data-access/**/*.ts`,
Expand Down Expand Up @@ -445,7 +444,6 @@ describe('move project', () => {
expect(workspaceJson.projects[`${lib1}-data-access`]).toBeUndefined();
const project = readProjectConfig(newName);
expect(project).toBeTruthy();
expect(project.root).toBe(newPath);
expect(project.sourceRoot).toBe(`${newPath}/src`);
expect(project.tags).toEqual([]);
const lib3Config = readProjectConfig(lib3);
Expand Down Expand Up @@ -578,7 +576,6 @@ describe('move project', () => {
expect(workspaceJson.projects[`${lib1}-data-access`]).toBeUndefined();
const project = readProjectConfig(newName);
expect(project).toBeTruthy();
expect(project.root).toBe(newPath);
expect(project.sourceRoot).toBe(`${newPath}/src`);
expect(project.targets.lint.options.lintFilePatterns).toEqual([
`packages/shared/${lib1}/data-access/**/*.ts`,
Expand Down
Expand Up @@ -46,6 +46,9 @@ function updateAppAndE2EProjectConfigurations(
options.ngCliSchematicAppRoot,
options.appProjectRoot
);
// project already has the right root, but the above function, makes it incorrect.
// This corrects it.
project.root = options.appProjectRoot;
}

delete project.targets.test;
Expand Down
3 changes: 3 additions & 0 deletions packages/angular/src/generators/library/lib/update-project.ts
Expand Up @@ -138,6 +138,9 @@ function fixProjectWorkspaceConfig(host: Tree, options: NormalizedSchema) {
options.ngCliSchematicLibRoot,
options.projectRoot
);
// project already has the right root, but the above function, makes it incorrect.
// This corrects it.
project.root = options.projectRoot;
}

if (!options.publishable && !options.buildable) {
Expand Down
8 changes: 4 additions & 4 deletions packages/devkit/index.ts
Expand Up @@ -12,7 +12,7 @@
/**
* @category Tree
*/
export type { Tree, FileChange } from 'nx/src/config/tree';
export type { Tree, FileChange } from 'nx/src/generators/tree';

/**
* @category Workspace
Expand Down Expand Up @@ -113,7 +113,7 @@ export { generateFiles } from './src/generators/generate-files';
/**
* @category Generators
*/
export type { WorkspaceConfiguration } from './src/generators/project-configuration';
export type { WorkspaceConfiguration } from 'nx/src/generators/utils/project-configuration';

/**
* @category Generators
Expand All @@ -127,7 +127,7 @@ export {
updateWorkspaceConfiguration,
getProjects,
isStandaloneProject,
} from './src/generators/project-configuration';
} from 'nx/src/generators/utils/project-configuration';

/**
* @category Generators
Expand Down Expand Up @@ -185,7 +185,7 @@ export { ProjectGraphBuilder } from 'nx/src/project-graph/project-graph-builder'
/**
* @category Utils
*/
export { readJson, writeJson, updateJson } from './src/utils/json';
export { readJson, writeJson, updateJson } from 'nx/src/generators/utils/json';

/**
* @category Utils
Expand Down
10 changes: 5 additions & 5 deletions packages/devkit/src/generators/format-files.ts
@@ -1,14 +1,14 @@
import type { Tree } from 'nx/src/config/tree';
import type { Tree } from 'nx/src/generators/tree';
import * as path from 'path';
import type * as Prettier from 'prettier';
import { getWorkspacePath } from '../utils/get-workspace-layout';
import { readJson, updateJson, writeJson } from '../utils/json';
import { sortObjectByKeys } from 'nx/src/utils/object-sort';
import { readJson, updateJson, writeJson } from 'nx/src/generators/utils/json';
import {
getWorkspacePath,
readWorkspaceConfiguration,
updateWorkspaceConfiguration,
WorkspaceConfiguration,
} from './project-configuration';
} from 'nx/src/generators/utils/project-configuration';
import { sortObjectByKeys } from 'nx/src/utils/object-sort';

/**
* Formats all the created or updated files using Prettier
Expand Down
4 changes: 2 additions & 2 deletions packages/devkit/src/generators/generate-files.spec.ts
@@ -1,5 +1,5 @@
import type { Tree } from 'nx/src/config/tree';
import { createTree } from '../tests/create-tree';
import type { Tree } from 'nx/src/generators/tree';
import { createTree } from 'nx/src/generators/testing-utils/create-tree';
import { generateFiles } from './generate-files';
import { join } from 'path';
import * as FileType from 'file-type';
Expand Down
2 changes: 1 addition & 1 deletion packages/devkit/src/generators/generate-files.ts
@@ -1,6 +1,6 @@
import { readFileSync, readdirSync, statSync } from 'fs';
import * as path from 'path';
import type { Tree } from 'nx/src/config/tree';
import type { Tree } from 'nx/src/generators/tree';
import { logger } from 'nx/src/utils/logger';

const binaryExts = new Set([
Expand Down
2 changes: 1 addition & 1 deletion packages/devkit/src/generators/to-js.ts
@@ -1,4 +1,4 @@
import type { Tree } from 'nx/src/config/tree';
import type { Tree } from 'nx/src/generators/tree';

/**
* Rename and transpile any new typescript files created to javascript files
Expand Down
4 changes: 2 additions & 2 deletions packages/devkit/src/generators/update-ts-configs-to-js.ts
@@ -1,5 +1,5 @@
import type { Tree } from 'nx/src/config/tree';
import { updateJson } from '../utils/json';
import type { Tree } from 'nx/src/generators/tree';
import { updateJson } from 'nx/src/generators/utils/json';

export function updateTsConfigsToJs(
tree: Tree,
Expand Down
@@ -1,5 +1,5 @@
import { createTree } from '../tests/create-tree';
import type { Tree } from 'nx/src/config/tree';
import { createTree } from 'nx/src/generators/testing-utils/create-tree';
import type { Tree } from 'nx/src/generators/tree';
import { visitNotIgnoredFiles } from './visit-not-ignored-files';

describe('visitNotIgnoredFiles', () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/devkit/src/generators/visit-not-ignored-files.ts
@@ -1,4 +1,4 @@
import type { Tree } from 'nx/src/config/tree';
import type { Tree } from 'nx/src/generators/tree';
import ignore, { Ignore } from 'ignore';
import { join, relative, sep } from 'path';

Expand Down
2 changes: 1 addition & 1 deletion packages/devkit/src/tasks/install-packages-task.ts
@@ -1,4 +1,4 @@
import type { Tree } from 'nx/src/config/tree';
import type { Tree } from 'nx/src/generators/tree';
import { execSync } from 'child_process';
import { join } from 'path';
import {
Expand Down
41 changes: 8 additions & 33 deletions packages/devkit/src/utils/get-workspace-layout.ts
@@ -1,9 +1,11 @@
import { RawWorkspaceJsonConfiguration } from 'nx/src/config/workspace-json-project-json';
import {
getWorkspacePath,
readNxJson,
shouldDefaultToUsingStandaloneConfigs,
} from 'nx/src/generators/utils/project-configuration';
import type { Tree } from 'nx/src/generators/tree';

import { readNxJson } from '../generators/project-configuration';
import { readJson } from './json';

import type { Tree } from 'nx/src/config/tree';
export { getWorkspacePath } from 'nx/src/generators/utils/project-configuration';

/**
* Returns workspace defaults. It includes defaults folders for apps and libs,
Expand All @@ -23,37 +25,10 @@ export function getWorkspaceLayout(tree: Tree): {
npmScope: string;
} {
const nxJson = readNxJson(tree);
const workspacePath = getWorkspacePath(tree);
const rawWorkspace =
workspacePath && tree.exists(workspacePath)
? readJson<RawWorkspaceJsonConfiguration>(tree, workspacePath)
: null;

return {
appsDir: nxJson?.workspaceLayout?.appsDir ?? 'apps',
libsDir: nxJson?.workspaceLayout?.libsDir ?? 'libs',
npmScope: nxJson?.npmScope ?? '',
standaloneAsDefault: !rawWorkspace
? true // if workspace.json doesn't exist, all projects **must** be standalone
: Object.values(rawWorkspace.projects).reduce(
// default for second, third... projects should be based on all projects being defined as a path
// for configuration read from ng schematics, this is determined by configFilePath's presence
(allStandalone, next) =>
allStandalone &&
(typeof next === 'string' || 'configFilePath' in next),

// default for first project should be true if using Nx Schema
rawWorkspace.version > 1
),
standaloneAsDefault: shouldDefaultToUsingStandaloneConfigs(tree),
};
}

export function getWorkspacePath(
tree: Tree
): '/angular.json' | '/workspace.json' | null {
const possibleFiles: ('/angular.json' | '/workspace.json')[] = [
'/angular.json',
'/workspace.json',
];
return possibleFiles.filter((path) => tree.exists(path))[0];
}
15 changes: 10 additions & 5 deletions packages/devkit/src/utils/invoke-nx-generator.ts
@@ -1,9 +1,13 @@
import { logger, stripIndent } from 'nx/src/utils/logger';
import type { FileChange, Tree, TreeWriteOptions } from 'nx/src/config/tree';
import type {
FileChange,
Tree,
TreeWriteOptions,
} from 'nx/src/generators/tree';
import { toNewFormat, toOldFormatOrNull } from 'nx/src/config/workspaces';
import { Generator, GeneratorCallback } from 'nx/src/config/misc-interfaces';
import { parseJson, serializeJson } from 'nx/src/utils/json';
import { join, relative } from 'path';
import { join, relative, dirname } from 'path';

class RunCallbackTask {
constructor(private callback: GeneratorCallback) {}
Expand Down Expand Up @@ -192,9 +196,10 @@ class DevkitTreeFromAngularDevkitTree implements Tree {
const w = parseJson(content.toString());
for (const [project, configuration] of Object.entries(w.projects)) {
if (typeof configuration === 'string') {
w.projects[project] = parseJson(
this.tree.read(`${configuration}/project.json`)
);
w.projects[project] = {
root: configuration,
...parseJson(this.tree.read(`${configuration}/project.json`)),
};
w.projects[project].configFilePath = `${configuration}/project.json`;
}
}
Expand Down
2 changes: 1 addition & 1 deletion packages/devkit/src/utils/move-dir.ts
@@ -1,4 +1,4 @@
import { Tree } from 'nx/src/config/tree';
import { Tree } from 'nx/src/generators/tree';
import { relative } from 'path';
import { visitNotIgnoredFiles } from '../generators/visit-not-ignored-files';
import { normalizePath } from 'nx/src/utils/path';
Expand Down
6 changes: 3 additions & 3 deletions packages/devkit/src/utils/package-json.spec.ts
@@ -1,7 +1,7 @@
import type { Tree } from 'nx/src/config/tree';
import { readJson, writeJson } from './json';
import type { Tree } from 'nx/src/generators/tree';
import { readJson, writeJson } from 'nx/src/generators/utils/json';
import { addDependenciesToPackageJson } from './package-json';
import { createTree } from '../tests/create-tree';
import { createTree } from 'nx/src/generators/testing-utils/create-tree';

describe('addDependenciesToPackageJson', () => {
let tree: Tree;
Expand Down
4 changes: 2 additions & 2 deletions packages/devkit/src/utils/package-json.ts
@@ -1,6 +1,6 @@
import { readJson, updateJson } from './json';
import { readJson, updateJson } from 'nx/src/generators/utils/json';
import { installPackagesTask } from '../tasks/install-packages-task';
import type { Tree } from 'nx/src/config/tree';
import type { Tree } from 'nx/src/generators/tree';
import { GeneratorCallback } from 'nx/src/config/misc-interfaces';

/**
Expand Down
4 changes: 2 additions & 2 deletions packages/devkit/testing.ts
@@ -1,2 +1,2 @@
export { createTreeWithEmptyWorkspace } from './src/tests/create-tree-with-empty-workspace';
export { createTree } from './src/tests/create-tree';
export { createTreeWithEmptyWorkspace } from 'nx/src/generators/testing-utils/create-tree-with-empty-workspace';
export { createTree } from 'nx/src/generators/testing-utils/create-tree';
Expand Up @@ -7,7 +7,7 @@ const mockResolveConfig = jest.fn(() =>
);

import { Tree } from '@nrwl/devkit';
import { createTreeWithEmptyWorkspace } from 'packages/devkit/src/tests/create-tree-with-empty-workspace';
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
import update from './update-base-jest-config';

describe('update 12.6.0', () => {
Expand Down
9 changes: 8 additions & 1 deletion packages/nx/migrations.json
@@ -1,3 +1,10 @@
{
"migrations": {}
"generators": {
"14-0-4-remove-root": {
"cli": "nx",
"version": "14.0.4",
"description": "Remove root property from project.json files",
"factory": "./src/migrations/update-14-0-4/remove-roots"
}
}
}
12 changes: 12 additions & 0 deletions packages/nx/migrations.spec.ts
@@ -0,0 +1,12 @@
import path = require('path');
import json = require('./migrations.json');

describe('Node migrations', () => {
it('should have valid paths', () => {
Object.values(json.generators).forEach((m) => {
expect(() =>
require.resolve(path.join(__dirname, `${m.factory}.ts`))
).not.toThrow();
});
});
});
12 changes: 8 additions & 4 deletions packages/nx/src/adapter/ngcli-adapter.ts
Expand Up @@ -15,7 +15,7 @@ import { createConsoleLogger, NodeJsSyncHost } from '@angular-devkit/core/node';
import { Stats } from 'fs';
import { detectPackageManager } from '../utils/package-manager';
import { GenerateOptions } from '../command-line/generate';
import { FileChange, Tree } from '../config/tree';
import { FileChange, Tree } from '../generators/tree';
import {
buildWorkspaceConfigurationFromGlobs,
globForProjectFiles,
Expand Down Expand Up @@ -497,6 +497,7 @@ export class NxScopedHost extends virtualFs.ScopedHost<any> {
// project was read from a project.json file
const configPath = projectConfig.configFilePath;
const fileConfigObject = { ...projectConfig };
delete fileConfigObject.root; // remove the root before writing
delete fileConfigObject.configFilePath; // remove the configFilePath before writing
const projectJsonWrite = super.write(
configPath,
Expand Down Expand Up @@ -539,6 +540,7 @@ export class NxScopedHost extends virtualFs.ScopedHost<any> {
map((x) => ({
project,
projectConfig: {
root: dirname(configFilePath),
...parseJson(Buffer.from(x).toString()),
configFilePath,
},
Expand Down Expand Up @@ -600,9 +602,10 @@ export class NxScopeHostUsedForWrappedSchematics extends NxScopedHost {
const nxJsonInTree = nxJsonChange
? parseJson(nxJsonChange.content.toString())
: parseJson(this.host.read('nx.json').toString());
const readJsonWithHost = (file) =>
parseJson(this.host.read(file).toString());

const readJsonWithHost = (file) => ({
root: dirname(file),
...parseJson(this.host.read(file).toString()),
});
const staticProjects = buildWorkspaceConfigurationFromGlobs(
nxJsonInTree,
globForProjectFiles(this.host.root).filter(
Expand Down Expand Up @@ -1214,6 +1217,7 @@ function saveWorkspaceConfigurationInWrappedSchematic(
) {
const path = config.configFilePath || join(config.root, 'project.json');
workspace.projects[project] = normalize(dirname(path));
delete config.root; // remove the root before writing
delete config.configFilePath;
host.write(path, serializeJson(config));
}
Expand Down
2 changes: 1 addition & 1 deletion packages/nx/src/command-line/generate.ts
Expand Up @@ -5,7 +5,7 @@ import {
Schema,
} from '../utils/params';
import { Workspaces } from '../config/workspaces';
import { FileChange, flushChanges, FsTree } from '../config/tree';
import { FileChange, flushChanges, FsTree } from '../generators/tree';
import { logger } from '../utils/logger';
import * as chalk from 'chalk';
import { workspaceRoot } from '../utils/app-root';
Expand Down
2 changes: 1 addition & 1 deletion packages/nx/src/command-line/migrate.ts
Expand Up @@ -8,7 +8,7 @@ import {
PackageJsonUpdateForPackage,
} from '../config/misc-interfaces';
import { NxJsonConfiguration } from '../config/nx-json';
import { flushChanges, FsTree } from '../config/tree';
import { flushChanges, FsTree } from '../generators/tree';
import {
extractFileFromTarball,
JsonReadOptions,
Expand Down

1 comment on commit 5e23c07

@vercel
Copy link

@vercel vercel bot commented on 5e23c07 Apr 28, 2022

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
nx-dev-nrwl.vercel.app
nx-five.vercel.app
nx-dev-git-master-nrwl.vercel.app

Please sign in to comment.