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 { SchematicTestRunner } from '@angular-devkit/schematics/testing';
|
||||
import {
|
||||
updateJsonInTree,
|
||||
readJsonInTree,
|
||||
updateWorkspaceInTree,
|
||||
readWorkspace,
|
||||
getWorkspacePath,
|
||||
} from '@nrwl/workspace';
|
||||
import { readWorkspace } from '@nrwl/workspace';
|
||||
|
||||
import * as taoWorkspace from '@nrwl/tao/src/shared/workspace';
|
||||
|
||||
import * as path from 'path';
|
||||
|
||||
@ -14,6 +10,12 @@ describe('Update 8-5-0', () => {
|
||||
let tree: Tree;
|
||||
let schematicRunner: SchematicTestRunner;
|
||||
|
||||
beforeAll(() => {
|
||||
jest
|
||||
.spyOn(taoWorkspace, 'workspaceConfigName')
|
||||
.mockReturnValue('workspace.json');
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
tree = Tree.empty();
|
||||
schematicRunner = new SchematicTestRunner(
|
||||
|
||||
@ -238,6 +238,11 @@ export class NxScopedHost extends virtualFs.ScopedHost<any> {
|
||||
nxJson,
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -359,7 +364,8 @@ export class NxScopedHost extends virtualFs.ScopedHost<any> {
|
||||
return of({
|
||||
isWorkspaceConfig: true,
|
||||
actualConfigFileName: null,
|
||||
isNewFormat: false,
|
||||
// AngularJson / WorkspaceJson v2 is always used for standalone project config
|
||||
isNewFormat: true,
|
||||
});
|
||||
}
|
||||
const actualConfigFileName = isAngularJson
|
||||
@ -463,7 +469,7 @@ export class NxScopedHost extends virtualFs.ScopedHost<any> {
|
||||
config
|
||||
) {
|
||||
// copy to avoid removing inlined config files.
|
||||
let writeObservable: Observable<void>;
|
||||
const writeObservables: Observable<void>[] = [];
|
||||
const configToWrite = {
|
||||
...config,
|
||||
projects: { ...config.projects },
|
||||
@ -471,7 +477,7 @@ export class NxScopedHost extends virtualFs.ScopedHost<any> {
|
||||
const projects: [string, any][] = Object.entries(configToWrite.projects);
|
||||
for (const [project, projectConfig] of projects) {
|
||||
if (projectConfig.configFilePath) {
|
||||
if (!isNewFormat) {
|
||||
if (workspaceFileName && !isNewFormat) {
|
||||
throw new Error(
|
||||
'Attempted to write standalone project configuration into a v1 workspace'
|
||||
);
|
||||
@ -484,9 +490,7 @@ export class NxScopedHost extends virtualFs.ScopedHost<any> {
|
||||
configPath,
|
||||
Buffer.from(serializeJson(fileConfigObject))
|
||||
); // write back to the project.json file
|
||||
writeObservable = writeObservable
|
||||
? merge(writeObservable, projectJsonWrite)
|
||||
: projectJsonWrite;
|
||||
writeObservables.push(projectJsonWrite);
|
||||
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,
|
||||
Buffer.from(serializeJson(configToWrite))
|
||||
);
|
||||
writeObservable = writeObservable
|
||||
? merge(writeObservable, workspaceJsonWrite)
|
||||
: workspaceJsonWrite;
|
||||
writeObservables.push(workspaceJsonWrite);
|
||||
}
|
||||
return writeObservable;
|
||||
return merge(...writeObservables);
|
||||
}
|
||||
|
||||
protected resolveInlineProjectConfigurations(
|
||||
|
||||
@ -11,6 +11,7 @@ const Module = require('module');
|
||||
const originalRequire = Module.prototype.require;
|
||||
|
||||
let patched = false;
|
||||
let loggedWriteWorkspaceWarning = false;
|
||||
|
||||
if (!patched) {
|
||||
Module.prototype.require = function () {
|
||||
@ -21,14 +22,34 @@ if (!patched) {
|
||||
`@angular-devkit/core/src/workspace/core`,
|
||||
]);
|
||||
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;
|
||||
core.writeWorkspace = (...args) => {
|
||||
const configFile = workspaceConfigName(appRootPath);
|
||||
logger.warn(
|
||||
`[NX] An Angular builder called \`writeWorkspace\`, this may have had unintended consequences in ${configFile}`
|
||||
);
|
||||
logger.warn(`[NX] Double check ${configFile} before proceeding`);
|
||||
originalWriteWorkspace.apply(this, args);
|
||||
if (!loggedWriteWorkspaceWarning) {
|
||||
if (configFile) {
|
||||
logger.warn(
|
||||
`[NX] Angular devkit called \`writeWorkspace\`, this may have had unintended consequences in ${configFile}`
|
||||
);
|
||||
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
|
||||
@ -37,20 +58,32 @@ if (!patched) {
|
||||
`@angular-devkit/core/src/workspace/json/reader`,
|
||||
]);
|
||||
const originalReadJsonWorkspace = readJsonUtils.readJsonWorkspace;
|
||||
readJsonUtils.readJsonWorkspace = () => {
|
||||
// Read our v1 workspace schema
|
||||
const w = resolveOldFormatWithInlineProjects(
|
||||
new Workspaces(appRootPath).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(w),
|
||||
},
|
||||
]);
|
||||
readJsonUtils.readJsonWorkspace = (
|
||||
path,
|
||||
host: { readFile: (p) => Promise<string> }
|
||||
) => {
|
||||
try {
|
||||
return originalReadJsonWorkspace(path, host);
|
||||
} catch {
|
||||
logger.debug(
|
||||
'[NX] Angular devkit readJsonWorkspace fell back to Nx workspaces logic'
|
||||
);
|
||||
const w = new Workspaces(appRootPath);
|
||||
|
||||
// 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;
|
||||
|
||||
@ -157,8 +157,10 @@ export interface TargetConfiguration {
|
||||
export function workspaceConfigName(root: string) {
|
||||
if (existsSync(path.join(root, 'angular.json'))) {
|
||||
return 'angular.json';
|
||||
} else {
|
||||
} else if (existsSync(path.join(root, 'workspace.json'))) {
|
||||
return 'workspace.json';
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -290,14 +292,18 @@ export class Workspaces {
|
||||
const nxJson = existsSync(nxJsonPath)
|
||||
? readJsonFile<NxJsonConfiguration>(nxJsonPath)
|
||||
: ({} as NxJsonConfiguration);
|
||||
const workspacePath = path.join(this.root, workspaceConfigName(this.root));
|
||||
const workspace = existsSync(workspacePath)
|
||||
? this.readFromWorkspaceJson()
|
||||
: buildWorkspaceConfigurationFromGlobs(
|
||||
nxJson,
|
||||
globForProjectFiles(this.root),
|
||||
(path) => readJsonFile(join(this.root, path))
|
||||
);
|
||||
const workspaceFile = workspaceConfigName(this.root);
|
||||
const workspacePath = workspaceFile
|
||||
? path.join(this.root, workspaceFile)
|
||||
: null;
|
||||
const workspace =
|
||||
workspacePath && existsSync(workspacePath)
|
||||
? this.readFromWorkspaceJson()
|
||||
: buildWorkspaceConfigurationFromGlobs(
|
||||
nxJson,
|
||||
globForProjectFiles(this.root),
|
||||
(path) => readJsonFile(join(this.root, path))
|
||||
);
|
||||
|
||||
assertValidWorkspaceConfiguration(nxJson);
|
||||
return { ...workspace, ...nxJson };
|
||||
@ -701,6 +707,7 @@ export function deduplicateProjectFiles(files: string[], ig?: Ignore) {
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
filtered.set(projectFolder, projectFile);
|
||||
});
|
||||
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 { callRule, runMigration } from '../../utils/testing';
|
||||
import { readJsonInTree, updateJsonInTree } from '../../utils/ast-utils';
|
||||
import type { NxJsonConfiguration } from '@nrwl/devkit';
|
||||
|
||||
describe('Update 8.12.0', () => {
|
||||
let tree: Tree;
|
||||
|
||||
@ -9,11 +9,10 @@ import { stripIndents } from '@angular-devkit/core/src/utils/literals';
|
||||
import { updateJsonInTree } from '../../utils/ast-utils';
|
||||
import type { WorkspaceJsonConfiguration } from '@nrwl/devkit';
|
||||
import { formatFiles } from '@nrwl/workspace/src/utils/rules/format-files';
|
||||
import { workspaceConfigName } from '@nrwl/tao/src/shared/workspace';
|
||||
|
||||
const addE2eImplicitDependencies: Rule = (tree: Tree) =>
|
||||
updateJsonInTree<WorkspaceJsonConfiguration>(
|
||||
workspaceConfigName(tree.root.path),
|
||||
'workspace.json', // ngcli-adapter should handle conversion of workspace file names
|
||||
(json) => {
|
||||
Object.keys(json.projects).forEach((proj) => {
|
||||
const implicitE2eName = proj.replace(/-e2e$/, '');
|
||||
|
||||
@ -3,12 +3,21 @@ import { Tree } from '@angular-devkit/schematics';
|
||||
|
||||
import * as prettier from 'prettier';
|
||||
import * as path from 'path';
|
||||
import * as taoWorkspace from '@nrwl/tao/src/shared/workspace';
|
||||
|
||||
import { formatFiles } from './format-files';
|
||||
import { appRootPath } from '@nrwl/tao/src/utils/app-root';
|
||||
|
||||
describe('formatFiles', () => {
|
||||
let tree: Tree;
|
||||
let schematicRunner: SchematicTestRunner;
|
||||
|
||||
beforeAll(() => {
|
||||
jest
|
||||
.spyOn(taoWorkspace, 'workspaceConfigName')
|
||||
.mockReturnValue('workspace.json');
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
schematicRunner = new SchematicTestRunner(
|
||||
'@nrwl/workspace',
|
||||
@ -106,7 +115,7 @@ describe('formatFiles', () => {
|
||||
});
|
||||
|
||||
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');
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user