fix(core): misc. ng cli compat layer fixes (#8141)
* fix(core): misc. ng cli compat layer fixes * chore(core): unit test fixes
This commit is contained in:
parent
1f44bbeed9
commit
a23284e9ce
@ -1,12 +1,8 @@
|
|||||||
import { Tree } from '@angular-devkit/schematics';
|
import { Tree } from '@angular-devkit/schematics';
|
||||||
import { SchematicTestRunner } from '@angular-devkit/schematics/testing';
|
import { SchematicTestRunner } from '@angular-devkit/schematics/testing';
|
||||||
import {
|
import { readWorkspace } from '@nrwl/workspace';
|
||||||
updateJsonInTree,
|
|
||||||
readJsonInTree,
|
import * as taoWorkspace from '@nrwl/tao/src/shared/workspace';
|
||||||
updateWorkspaceInTree,
|
|
||||||
readWorkspace,
|
|
||||||
getWorkspacePath,
|
|
||||||
} from '@nrwl/workspace';
|
|
||||||
|
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
|
|
||||||
@ -14,6 +10,12 @@ describe('Update 8-5-0', () => {
|
|||||||
let tree: Tree;
|
let tree: Tree;
|
||||||
let schematicRunner: SchematicTestRunner;
|
let schematicRunner: SchematicTestRunner;
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
jest
|
||||||
|
.spyOn(taoWorkspace, 'workspaceConfigName')
|
||||||
|
.mockReturnValue('workspace.json');
|
||||||
|
});
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
tree = Tree.empty();
|
tree = Tree.empty();
|
||||||
schematicRunner = new SchematicTestRunner(
|
schematicRunner = new SchematicTestRunner(
|
||||||
|
|||||||
@ -238,6 +238,11 @@ export class NxScopedHost extends virtualFs.ScopedHost<any> {
|
|||||||
nxJson,
|
nxJson,
|
||||||
staticProjects.filter((x) => basename(x) !== 'package.json')
|
staticProjects.filter((x) => basename(x) !== 'package.json')
|
||||||
);
|
);
|
||||||
|
Object.entries(this.__nxInMemoryWorkspace.projects).forEach(
|
||||||
|
([project, config]) => {
|
||||||
|
this.__nxInMemoryWorkspace.projects[project] = config.root as any;
|
||||||
|
}
|
||||||
|
);
|
||||||
return of(this.__nxInMemoryWorkspace);
|
return of(this.__nxInMemoryWorkspace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -359,7 +364,8 @@ export class NxScopedHost extends virtualFs.ScopedHost<any> {
|
|||||||
return of({
|
return of({
|
||||||
isWorkspaceConfig: true,
|
isWorkspaceConfig: true,
|
||||||
actualConfigFileName: null,
|
actualConfigFileName: null,
|
||||||
isNewFormat: false,
|
// AngularJson / WorkspaceJson v2 is always used for standalone project config
|
||||||
|
isNewFormat: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
const actualConfigFileName = isAngularJson
|
const actualConfigFileName = isAngularJson
|
||||||
@ -463,7 +469,7 @@ export class NxScopedHost extends virtualFs.ScopedHost<any> {
|
|||||||
config
|
config
|
||||||
) {
|
) {
|
||||||
// copy to avoid removing inlined config files.
|
// copy to avoid removing inlined config files.
|
||||||
let writeObservable: Observable<void>;
|
const writeObservables: Observable<void>[] = [];
|
||||||
const configToWrite = {
|
const configToWrite = {
|
||||||
...config,
|
...config,
|
||||||
projects: { ...config.projects },
|
projects: { ...config.projects },
|
||||||
@ -471,7 +477,7 @@ export class NxScopedHost extends virtualFs.ScopedHost<any> {
|
|||||||
const projects: [string, any][] = Object.entries(configToWrite.projects);
|
const projects: [string, any][] = Object.entries(configToWrite.projects);
|
||||||
for (const [project, projectConfig] of projects) {
|
for (const [project, projectConfig] of projects) {
|
||||||
if (projectConfig.configFilePath) {
|
if (projectConfig.configFilePath) {
|
||||||
if (!isNewFormat) {
|
if (workspaceFileName && !isNewFormat) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
'Attempted to write standalone project configuration into a v1 workspace'
|
'Attempted to write standalone project configuration into a v1 workspace'
|
||||||
);
|
);
|
||||||
@ -484,9 +490,7 @@ export class NxScopedHost extends virtualFs.ScopedHost<any> {
|
|||||||
configPath,
|
configPath,
|
||||||
Buffer.from(serializeJson(fileConfigObject))
|
Buffer.from(serializeJson(fileConfigObject))
|
||||||
); // write back to the project.json file
|
); // write back to the project.json file
|
||||||
writeObservable = writeObservable
|
writeObservables.push(projectJsonWrite);
|
||||||
? merge(writeObservable, projectJsonWrite)
|
|
||||||
: projectJsonWrite;
|
|
||||||
configToWrite.projects[project] = normalize(dirname(configPath)); // update the config object to point to the written file.
|
configToWrite.projects[project] = normalize(dirname(configPath)); // update the config object to point to the written file.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -496,11 +500,9 @@ export class NxScopedHost extends virtualFs.ScopedHost<any> {
|
|||||||
workspaceFileName,
|
workspaceFileName,
|
||||||
Buffer.from(serializeJson(configToWrite))
|
Buffer.from(serializeJson(configToWrite))
|
||||||
);
|
);
|
||||||
writeObservable = writeObservable
|
writeObservables.push(workspaceJsonWrite);
|
||||||
? merge(writeObservable, workspaceJsonWrite)
|
|
||||||
: workspaceJsonWrite;
|
|
||||||
}
|
}
|
||||||
return writeObservable;
|
return merge(...writeObservables);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected resolveInlineProjectConfigurations(
|
protected resolveInlineProjectConfigurations(
|
||||||
|
|||||||
@ -11,6 +11,7 @@ const Module = require('module');
|
|||||||
const originalRequire = Module.prototype.require;
|
const originalRequire = Module.prototype.require;
|
||||||
|
|
||||||
let patched = false;
|
let patched = false;
|
||||||
|
let loggedWriteWorkspaceWarning = false;
|
||||||
|
|
||||||
if (!patched) {
|
if (!patched) {
|
||||||
Module.prototype.require = function () {
|
Module.prototype.require = function () {
|
||||||
@ -21,14 +22,34 @@ if (!patched) {
|
|||||||
`@angular-devkit/core/src/workspace/core`,
|
`@angular-devkit/core/src/workspace/core`,
|
||||||
]);
|
]);
|
||||||
core._test_addWorkspaceFile('workspace.json', core.WorkspaceFormat.JSON);
|
core._test_addWorkspaceFile('workspace.json', core.WorkspaceFormat.JSON);
|
||||||
|
const originalReadWorkspace = core.readWorkspace;
|
||||||
|
core.readWorkspace = (path, ...rest) => {
|
||||||
|
const configFile = workspaceConfigName(appRootPath);
|
||||||
|
if (!configFile) {
|
||||||
|
path = 'workspace.json';
|
||||||
|
}
|
||||||
|
return originalReadWorkspace.apply(this, [path, ...rest]);
|
||||||
|
};
|
||||||
const originalWriteWorkspace = core.writeWorkspace;
|
const originalWriteWorkspace = core.writeWorkspace;
|
||||||
core.writeWorkspace = (...args) => {
|
core.writeWorkspace = (...args) => {
|
||||||
const configFile = workspaceConfigName(appRootPath);
|
const configFile = workspaceConfigName(appRootPath);
|
||||||
logger.warn(
|
if (!loggedWriteWorkspaceWarning) {
|
||||||
`[NX] An Angular builder called \`writeWorkspace\`, this may have had unintended consequences in ${configFile}`
|
if (configFile) {
|
||||||
);
|
logger.warn(
|
||||||
logger.warn(`[NX] Double check ${configFile} before proceeding`);
|
`[NX] Angular devkit called \`writeWorkspace\`, this may have had unintended consequences in ${configFile}`
|
||||||
originalWriteWorkspace.apply(this, args);
|
);
|
||||||
|
logger.warn(`[NX] Double check ${configFile} before proceeding`);
|
||||||
|
} else {
|
||||||
|
logger.warn(
|
||||||
|
`[NX] Angular devkit called \`writeWorkspace\`, this may have created 'workspace.json' or 'angular.json`
|
||||||
|
);
|
||||||
|
logger.warn(
|
||||||
|
`[NX] Double check workspace configuration before proceeding`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
loggedWriteWorkspaceWarning = true;
|
||||||
|
}
|
||||||
|
return originalWriteWorkspace.apply(this, args);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Patch readJsonWorkspace to inline project configurations
|
// Patch readJsonWorkspace to inline project configurations
|
||||||
@ -37,20 +58,32 @@ if (!patched) {
|
|||||||
`@angular-devkit/core/src/workspace/json/reader`,
|
`@angular-devkit/core/src/workspace/json/reader`,
|
||||||
]);
|
]);
|
||||||
const originalReadJsonWorkspace = readJsonUtils.readJsonWorkspace;
|
const originalReadJsonWorkspace = readJsonUtils.readJsonWorkspace;
|
||||||
readJsonUtils.readJsonWorkspace = () => {
|
readJsonUtils.readJsonWorkspace = (
|
||||||
// Read our v1 workspace schema
|
path,
|
||||||
const w = resolveOldFormatWithInlineProjects(
|
host: { readFile: (p) => Promise<string> }
|
||||||
new Workspaces(appRootPath).readWorkspaceConfiguration()
|
) => {
|
||||||
);
|
try {
|
||||||
// readJsonWorkspace actually has AST parsing + more, so we
|
return originalReadJsonWorkspace(path, host);
|
||||||
// still need to call it rather than just return our file
|
} catch {
|
||||||
return originalReadJsonWorkspace.apply(this, [
|
logger.debug(
|
||||||
'workspace.json', // path name, doesn't matter
|
'[NX] Angular devkit readJsonWorkspace fell back to Nx workspaces logic'
|
||||||
{
|
);
|
||||||
// second arg is a host, only method used is readFile
|
const w = new Workspaces(appRootPath);
|
||||||
readFile: () => JSON.stringify(w),
|
|
||||||
},
|
// Read our v1 workspace schema
|
||||||
]);
|
const workspaceConfiguration = resolveOldFormatWithInlineProjects(
|
||||||
|
w.readWorkspaceConfiguration()
|
||||||
|
);
|
||||||
|
// readJsonWorkspace actually has AST parsing + more, so we
|
||||||
|
// still need to call it rather than just return our file
|
||||||
|
return originalReadJsonWorkspace.apply(this, [
|
||||||
|
'workspace.json', // path name, doesn't matter
|
||||||
|
{
|
||||||
|
// second arg is a host, only method used is readFile
|
||||||
|
readFile: () => JSON.stringify(workspaceConfiguration),
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@ -157,8 +157,10 @@ export interface TargetConfiguration {
|
|||||||
export function workspaceConfigName(root: string) {
|
export function workspaceConfigName(root: string) {
|
||||||
if (existsSync(path.join(root, 'angular.json'))) {
|
if (existsSync(path.join(root, 'angular.json'))) {
|
||||||
return 'angular.json';
|
return 'angular.json';
|
||||||
} else {
|
} else if (existsSync(path.join(root, 'workspace.json'))) {
|
||||||
return 'workspace.json';
|
return 'workspace.json';
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -290,14 +292,18 @@ export class Workspaces {
|
|||||||
const nxJson = existsSync(nxJsonPath)
|
const nxJson = existsSync(nxJsonPath)
|
||||||
? readJsonFile<NxJsonConfiguration>(nxJsonPath)
|
? readJsonFile<NxJsonConfiguration>(nxJsonPath)
|
||||||
: ({} as NxJsonConfiguration);
|
: ({} as NxJsonConfiguration);
|
||||||
const workspacePath = path.join(this.root, workspaceConfigName(this.root));
|
const workspaceFile = workspaceConfigName(this.root);
|
||||||
const workspace = existsSync(workspacePath)
|
const workspacePath = workspaceFile
|
||||||
? this.readFromWorkspaceJson()
|
? path.join(this.root, workspaceFile)
|
||||||
: buildWorkspaceConfigurationFromGlobs(
|
: null;
|
||||||
nxJson,
|
const workspace =
|
||||||
globForProjectFiles(this.root),
|
workspacePath && existsSync(workspacePath)
|
||||||
(path) => readJsonFile(join(this.root, path))
|
? this.readFromWorkspaceJson()
|
||||||
);
|
: buildWorkspaceConfigurationFromGlobs(
|
||||||
|
nxJson,
|
||||||
|
globForProjectFiles(this.root),
|
||||||
|
(path) => readJsonFile(join(this.root, path))
|
||||||
|
);
|
||||||
|
|
||||||
assertValidWorkspaceConfiguration(nxJson);
|
assertValidWorkspaceConfiguration(nxJson);
|
||||||
return { ...workspace, ...nxJson };
|
return { ...workspace, ...nxJson };
|
||||||
@ -701,6 +707,7 @@ export function deduplicateProjectFiles(files: string[], ig?: Ignore) {
|
|||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
filtered.set(projectFolder, projectFile);
|
filtered.set(projectFolder, projectFile);
|
||||||
});
|
});
|
||||||
return Array.from(filtered.entries()).map(([folder, file]) =>
|
return Array.from(filtered.entries()).map(([folder, file]) =>
|
||||||
|
|||||||
@ -2,7 +2,6 @@ import { Tree } from '@angular-devkit/schematics';
|
|||||||
import { createEmptyWorkspace } from '../../utils/testing-utils';
|
import { createEmptyWorkspace } from '../../utils/testing-utils';
|
||||||
import { callRule, runMigration } from '../../utils/testing';
|
import { callRule, runMigration } from '../../utils/testing';
|
||||||
import { readJsonInTree, updateJsonInTree } from '../../utils/ast-utils';
|
import { readJsonInTree, updateJsonInTree } from '../../utils/ast-utils';
|
||||||
import type { NxJsonConfiguration } from '@nrwl/devkit';
|
|
||||||
|
|
||||||
describe('Update 8.12.0', () => {
|
describe('Update 8.12.0', () => {
|
||||||
let tree: Tree;
|
let tree: Tree;
|
||||||
|
|||||||
@ -9,11 +9,10 @@ import { stripIndents } from '@angular-devkit/core/src/utils/literals';
|
|||||||
import { updateJsonInTree } from '../../utils/ast-utils';
|
import { updateJsonInTree } from '../../utils/ast-utils';
|
||||||
import type { WorkspaceJsonConfiguration } from '@nrwl/devkit';
|
import type { WorkspaceJsonConfiguration } from '@nrwl/devkit';
|
||||||
import { formatFiles } from '@nrwl/workspace/src/utils/rules/format-files';
|
import { formatFiles } from '@nrwl/workspace/src/utils/rules/format-files';
|
||||||
import { workspaceConfigName } from '@nrwl/tao/src/shared/workspace';
|
|
||||||
|
|
||||||
const addE2eImplicitDependencies: Rule = (tree: Tree) =>
|
const addE2eImplicitDependencies: Rule = (tree: Tree) =>
|
||||||
updateJsonInTree<WorkspaceJsonConfiguration>(
|
updateJsonInTree<WorkspaceJsonConfiguration>(
|
||||||
workspaceConfigName(tree.root.path),
|
'workspace.json', // ngcli-adapter should handle conversion of workspace file names
|
||||||
(json) => {
|
(json) => {
|
||||||
Object.keys(json.projects).forEach((proj) => {
|
Object.keys(json.projects).forEach((proj) => {
|
||||||
const implicitE2eName = proj.replace(/-e2e$/, '');
|
const implicitE2eName = proj.replace(/-e2e$/, '');
|
||||||
|
|||||||
@ -3,12 +3,21 @@ import { Tree } from '@angular-devkit/schematics';
|
|||||||
|
|
||||||
import * as prettier from 'prettier';
|
import * as prettier from 'prettier';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
|
import * as taoWorkspace from '@nrwl/tao/src/shared/workspace';
|
||||||
|
|
||||||
import { formatFiles } from './format-files';
|
import { formatFiles } from './format-files';
|
||||||
import { appRootPath } from '@nrwl/tao/src/utils/app-root';
|
import { appRootPath } from '@nrwl/tao/src/utils/app-root';
|
||||||
|
|
||||||
describe('formatFiles', () => {
|
describe('formatFiles', () => {
|
||||||
let tree: Tree;
|
let tree: Tree;
|
||||||
let schematicRunner: SchematicTestRunner;
|
let schematicRunner: SchematicTestRunner;
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
jest
|
||||||
|
.spyOn(taoWorkspace, 'workspaceConfigName')
|
||||||
|
.mockReturnValue('workspace.json');
|
||||||
|
});
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
schematicRunner = new SchematicTestRunner(
|
schematicRunner = new SchematicTestRunner(
|
||||||
'@nrwl/workspace',
|
'@nrwl/workspace',
|
||||||
@ -106,7 +115,7 @@ describe('formatFiles', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should have a readable error when workspace file cannot be formatted', async () => {
|
it('should have a readable error when workspace file cannot be formatted', async () => {
|
||||||
tree.delete('workspace.json');
|
tree.overwrite('workspace.json', '{ invalidJson: true');
|
||||||
|
|
||||||
const errorSpy = jest.spyOn(console, 'error');
|
const errorSpy = jest.spyOn(console, 'error');
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user