Skip to content

Commit 14c49bd

Browse files
clydinmgechev
authored andcommitted
refactor(@schematics/angular): use new JSON helpers in v6 migration
1 parent fa808f7 commit 14c49bd

File tree

1 file changed

+52
-110
lines changed
  • packages/schematics/angular/migrations/update-6

1 file changed

+52
-110
lines changed

packages/schematics/angular/migrations/update-6/index.ts

Lines changed: 52 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import {
1414
logging,
1515
normalize,
1616
parseJson,
17-
parseJsonAst,
1817
tags,
1918
} from '@angular-devkit/core';
2019
import {
@@ -31,10 +30,7 @@ import {
3130
NodeDependencyType,
3231
addPackageJsonDependency,
3332
} from '../../utility/dependencies';
34-
import {
35-
appendValueInAstArray,
36-
findPropertyInAstObject,
37-
} from '../../utility/json-utils';
33+
import { JSONFile } from '../../utility/json-file';
3834
import { latestVersions } from '../../utility/latest-versions';
3935

4036
const defaults = {
@@ -624,41 +620,35 @@ function extractDefaultProject(config: CliConfig): string | null {
624620
}
625621

626622
function updateSpecTsConfig(config: CliConfig): Rule {
627-
return (host: Tree, context: SchematicContext) => {
623+
return (host) => {
628624
const apps = config.apps || [];
629-
apps.forEach((app: AppConfig, idx: number) => {
625+
apps.forEach((app: AppConfig) => {
630626
const testTsConfig = app.testTsconfig || defaults.testTsConfig;
631627
const tsSpecConfigPath = join(normalize(app.root || ''), testTsConfig);
632-
const buffer = host.read(tsSpecConfigPath);
633628

634-
if (!buffer) {
629+
let tsConfigJson;
630+
try {
631+
tsConfigJson = new JSONFile(host, tsSpecConfigPath);
632+
} catch {
635633
return;
636634
}
637635

638-
639-
const tsCfgAst = parseJsonAst(buffer.toString(), JsonParseMode.Loose);
640-
if (tsCfgAst.kind != 'object') {
641-
throw new SchematicsException('Invalid tsconfig. Was expecting an object');
636+
const files = tsConfigJson.get(['files']);
637+
if (files === undefined) {
638+
// Do nothing if the files array does not exist. This means exclude or include are
639+
// set and we shouldn't mess with that.
640+
return;
642641
}
643642

644-
const filesAstNode = findPropertyInAstObject(tsCfgAst, 'files');
645-
if (filesAstNode && filesAstNode.kind != 'array') {
643+
if (!Array.isArray(files)) {
646644
throw new SchematicsException('Invalid tsconfig "files" property; expected an array.');
647645
}
648646

649-
const recorder = host.beginUpdate(tsSpecConfigPath);
650-
651647
const polyfills = app.polyfills || defaults.polyfills;
652-
if (!filesAstNode) {
653-
// Do nothing if the files array does not exist. This means exclude or include are
654-
// set and we shouldn't mess with that.
655-
} else {
656-
if (filesAstNode.value.indexOf(polyfills) == -1) {
657-
appendValueInAstArray(recorder, filesAstNode, polyfills);
658-
}
648+
if (polyfills && !files.includes(polyfills)) {
649+
// Append polyfills file to the files array
650+
tsConfigJson.modify(['files', -1], polyfills);
659651
}
660-
661-
host.commitUpdate(recorder);
662652
});
663653
};
664654
}
@@ -682,111 +672,63 @@ function updatePackageJson(config: CliConfig) {
682672
}
683673

684674
function updateTsLintConfig(): Rule {
685-
return (host: Tree, context: SchematicContext) => {
675+
return (host) => {
686676
const tsLintPath = '/tslint.json';
687-
const buffer = host.read(tsLintPath);
688-
if (!buffer) {
689-
return host;
690-
}
691-
const tsCfgAst = parseJsonAst(buffer.toString(), JsonParseMode.Loose);
692-
693-
if (tsCfgAst.kind != 'object') {
694-
return host;
695-
}
696-
697-
const rulesNode = findPropertyInAstObject(tsCfgAst, 'rules');
698-
if (!rulesNode || rulesNode.kind != 'object') {
699-
return host;
700-
}
701677

702-
const importBlacklistNode = findPropertyInAstObject(rulesNode, 'import-blacklist');
703-
if (!importBlacklistNode || importBlacklistNode.kind != 'array') {
704-
return host;
678+
let tsLintJson;
679+
try {
680+
tsLintJson = new JSONFile(host, tsLintPath);
681+
} catch {
682+
return;
705683
}
706684

707-
const recorder = host.beginUpdate(tsLintPath);
708-
for (let i = 0; i < importBlacklistNode.elements.length; i++) {
709-
const element = importBlacklistNode.elements[i];
710-
if (element.kind == 'string' && element.value == 'rxjs') {
711-
const { start, end } = element;
712-
// Remove this element.
713-
if (i == importBlacklistNode.elements.length - 1) {
714-
// Last element.
715-
if (i > 0) {
716-
// Not first, there's a comma to remove before.
717-
const previous = importBlacklistNode.elements[i - 1];
718-
recorder.remove(previous.end.offset, end.offset - previous.end.offset);
719-
} else {
720-
// Only element, just remove the whole rule.
721-
const { start, end } = importBlacklistNode;
722-
recorder.remove(start.offset, end.offset - start.offset);
723-
recorder.insertLeft(start.offset, '[]');
724-
}
725-
} else {
726-
// Middle, just remove the whole node (up to next node start).
727-
const next = importBlacklistNode.elements[i + 1];
728-
recorder.remove(start.offset, next.start.offset - start.offset);
729-
}
730-
}
685+
const rulePath = ['rules', 'import-blacklist'];
686+
const currentRuleItems = tsLintJson.get(rulePath);
687+
if (!currentRuleItems || !Array.isArray(currentRuleItems)) {
688+
return;
731689
}
732690

733-
host.commitUpdate(recorder);
734-
735-
return host;
691+
// Remove all occurences of rxjs
692+
const newRuleItems = currentRuleItems.filter(value => value !== 'rxjs');
693+
tsLintJson.modify(rulePath, newRuleItems);
736694
};
737695
}
738696

739697
function updateRootTsConfig(): Rule {
740698
return (host: Tree, context: SchematicContext) => {
741699
const tsConfigPath = '/tsconfig.json';
742-
const buffer = host.read(tsConfigPath);
743-
if (!buffer) {
744-
return;
745-
}
746-
747-
const tsCfgAst = parseJsonAst(buffer.toString(), JsonParseMode.Loose);
748-
if (tsCfgAst.kind !== 'object') {
749-
throw new SchematicsException('Invalid root tsconfig. Was expecting an object');
750-
}
751-
752-
const compilerOptionsAstNode = findPropertyInAstObject(tsCfgAst, 'compilerOptions');
753-
if (!compilerOptionsAstNode || compilerOptionsAstNode.kind != 'object') {
754-
throw new SchematicsException(
755-
'Invalid root tsconfig "compilerOptions" property; expected an object.',
756-
);
757-
}
758700

759-
if (
760-
findPropertyInAstObject(compilerOptionsAstNode, 'baseUrl') &&
761-
findPropertyInAstObject(compilerOptionsAstNode, 'module')
762-
) {
763-
return host;
701+
let tsConfigJson;
702+
try {
703+
tsConfigJson = new JSONFile(host, tsConfigPath);
704+
} catch {
705+
return;
764706
}
765707

766-
const compilerOptions = compilerOptionsAstNode.value;
767-
const { baseUrl = './', module = 'es2015'} = compilerOptions;
768-
769-
const validBaseUrl = ['./', '', '.'];
770-
if (!validBaseUrl.includes(baseUrl as string)) {
771-
const formattedBaseUrl = validBaseUrl.map(x => `'${x}'`).join(', ');
772-
context.logger.warn(tags.oneLine
773-
`Root tsconfig option 'baseUrl' is not one of: ${formattedBaseUrl}.
774-
This might cause unexpected behaviour when generating libraries.`,
775-
);
708+
const baseUrlPath = ['compilerOptions', 'baseUrl'];
709+
const baseUrl = tsConfigJson.get(baseUrlPath);
710+
if (baseUrl === undefined || typeof baseUrl !== 'string') {
711+
tsConfigJson.modify(baseUrlPath, './');
712+
} else {
713+
const validBaseUrl = ['./', '', '.'];
714+
if (!validBaseUrl.includes(baseUrl)) {
715+
const formattedBaseUrl = validBaseUrl.map(x => `'${x}'`).join(', ');
716+
context.logger.warn(tags.oneLine
717+
`Root tsconfig option 'baseUrl' is not one of: ${formattedBaseUrl}.
718+
This might cause unexpected behaviour when generating libraries.`,
719+
);
720+
}
776721
}
777722

778-
if (module !== 'es2015') {
723+
const modulePath = ['compilerOptions', 'module'];
724+
const module = tsConfigJson.get(modulePath);
725+
if (module === undefined || typeof module !== 'string') {
726+
tsConfigJson.modify(modulePath, 'es2015');
727+
} else if (module.toLowerCase() !== 'es2015') {
779728
context.logger.warn(
780729
`Root tsconfig option 'module' is not 'es2015'. This might cause unexpected behaviour.`,
781730
);
782731
}
783-
784-
compilerOptions.module = module;
785-
compilerOptions.baseUrl = baseUrl;
786-
787-
host.overwrite(tsConfigPath, JSON.stringify(tsCfgAst.value, null, 2));
788-
789-
return host;
790732
};
791733
}
792734

0 commit comments

Comments
 (0)