fix(core): migrate tsconfig references in eslintrc (#3373)

This commit is contained in:
Jason Jean 2020-07-20 18:34:43 -04:00 committed by GitHub
parent 39a34a9836
commit 64c09f2d46
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 133 additions and 42 deletions

View File

@ -99,6 +99,11 @@
"version": "10.0.0-beta.0",
"description": "Migrate tsconfigs to solution style tsconfigs",
"factory": "./src/migrations/update-10-0-0/solution-tsconfigs"
},
"migrate-eslintrc-tsconfig": {
"version": "10.0.1-beta.0",
"description": "Migrate .eslintrc files to reference new tsconfig",
"factory": "./src/migrations/update-10-0-1/migrate-eslintrc"
}
},
"packageJsonUpdates": {

View File

@ -1,19 +1,13 @@
import { basename, dirname, join, normalize, Path } from '@angular-devkit/core';
import {
callRule,
chain,
Rule,
SchematicContext,
Tree,
} from '@angular-devkit/schematics';
import { chain, Rule, Tree } from '@angular-devkit/schematics';
import {
formatFiles,
NxJson,
readJsonInTree,
updateJsonInTree,
} from '@nrwl/workspace';
import ignore from 'ignore';
import { relative } from 'path';
import { visitNotIgnoredFiles } from '../../utils/rules/visit-not-ignored-files';
function renameRootTsconfig(host: Tree) {
if (!host.exists('tsconfig.json')) {
@ -23,40 +17,6 @@ function renameRootTsconfig(host: Tree) {
host.rename('tsconfig.json', 'tsconfig.base.json');
}
function visitNotIgnoredFiles(
visitor: (file: Path, host: Tree, context: SchematicContext) => void | Rule,
dir: Path = normalize('')
): Rule {
return (host, context) => {
let ig;
if (host.exists('.gitignore')) {
ig = ignore();
ig.add(host.read('.gitignore').toString());
}
function visit(_dir: Path) {
if (_dir && ig?.ignores(_dir)) {
return;
}
const dirEntry = host.getDir(_dir);
dirEntry.subfiles.forEach((file) => {
if (ig?.ignores(join(_dir, file))) {
return;
}
const maybeRule = visitor(join(_dir, file), host, context);
if (maybeRule) {
callRule(maybeRule, host, context).subscribe();
}
});
dirEntry.subdirs.forEach((subdir) => {
visit(join(_dir, subdir));
});
}
visit(dir);
};
}
function moveIncludesToProjectTsconfig(
file: Path,
extendedTsconfigPath: Path,

View File

@ -0,0 +1,53 @@
import { Tree } from '@angular-devkit/schematics';
import { callRule, runMigration } from '../../utils/testing';
import { readJsonInTree, updateJsonInTree } from '@nrwl/workspace';
describe('Eslintrc Migration', () => {
let tree: Tree;
beforeEach(async () => {
tree = Tree.empty();
tree = await callRule(
updateJsonInTree('.eslintrc', () => ({
parserOptions: {
project: './tsconfig.json',
},
})),
tree
);
tree = await callRule(
updateJsonInTree('project1/.eslintrc', () => ({
parserOptions: {
project: '../tsconfig.json',
},
})),
tree
);
tree = await callRule(
updateJsonInTree('project2/.eslintrc', () => ({
parserOptions: {
project: './tsconfig.json',
},
})),
tree
);
});
it('should reference tsconfig.base.json', async () => {
const result = await runMigration('migrate-eslintrc-tsconfig', {}, tree);
const eslintrc = readJsonInTree(result, '.eslintrc');
expect(eslintrc.parserOptions.project).toEqual('./tsconfig.base.json');
});
it('should reference tsconfig.base.json from .eslintrc files not in the root', async () => {
const result = await runMigration('migrate-eslintrc-tsconfig', {}, tree);
const eslintrc = readJsonInTree(result, 'project1/.eslintrc');
expect(eslintrc.parserOptions.project).toEqual('../tsconfig.base.json');
});
it("should reference tsconfig.base.json in .eslintrc that don't reference the root tsconfig.json", async () => {
const result = await runMigration('migrate-eslintrc-tsconfig', {}, tree);
const eslintrc = readJsonInTree(result, 'project2/.eslintrc');
expect(eslintrc.parserOptions.project).toEqual('./tsconfig.json');
});
});

View File

@ -0,0 +1,31 @@
import { basename, dirname, join } from '@angular-devkit/core';
import { chain, Rule } from '@angular-devkit/schematics';
import { formatFiles, updateJsonInTree } from '@nrwl/workspace';
import { visitNotIgnoredFiles } from '../../utils/rules/visit-not-ignored-files';
export default function (schema: any): Rule {
return chain([
visitNotIgnoredFiles((file, host, context) => {
if (basename(file) !== '.eslintrc') {
return;
}
return updateJsonInTree(file, (json) => {
const tsconfig = json?.parserOptions?.project;
if (tsconfig) {
const tsconfigPath = join(dirname(file), tsconfig);
if (tsconfigPath === 'tsconfig.json') {
json.parserOptions.project = json.parserOptions.project.replace(
/tsconfig.json$/,
'tsconfig.base.json'
);
}
return json;
} else {
return json;
}
});
}),
formatFiles(),
]);
}

View File

@ -0,0 +1,42 @@
import { join, normalize, Path } from '@angular-devkit/core';
import {
callRule,
Rule,
SchematicContext,
Tree,
} from '@angular-devkit/schematics';
import ignore from 'ignore';
export function visitNotIgnoredFiles(
visitor: (file: Path, host: Tree, context: SchematicContext) => void | Rule,
dir: Path = normalize('')
): Rule {
return (host, context) => {
let ig;
if (host.exists('.gitignore')) {
ig = ignore();
ig.add(host.read('.gitignore').toString());
}
function visit(_dir: Path) {
if (_dir && ig?.ignores(_dir)) {
return;
}
const dirEntry = host.getDir(_dir);
dirEntry.subfiles.forEach((file) => {
if (ig?.ignores(join(_dir, file))) {
return;
}
const maybeRule = visitor(join(_dir, file), host, context);
if (maybeRule) {
callRule(maybeRule, host, context).subscribe();
}
});
dirEntry.subdirs.forEach((subdir) => {
visit(join(_dir, subdir));
});
}
visit(dir);
};
}