diff --git a/packages/schematics/angular/migrations/update-6/index.ts b/packages/schematics/angular/migrations/update-6/index.ts index a6cf7c0c32a5..27e74d77ce1c 100644 --- a/packages/schematics/angular/migrations/update-6/index.ts +++ b/packages/schematics/angular/migrations/update-6/index.ts @@ -724,6 +724,60 @@ function updateTsLintConfig(): Rule { }; } +function updateRootTsConfig(): Rule { + return (host: Tree, context: SchematicContext) => { + const tsConfigPath = '/tsconfig.json'; + const buffer = host.read(tsConfigPath); + if (!buffer) { + return; + } + + const tsCfgAst = parseJsonAst(buffer.toString(), JsonParseMode.Loose); + if (tsCfgAst.kind !== 'object') { + throw new SchematicsException('Invalid root tsconfig. Was expecting an object'); + } + + const compilerOptionsAstNode = findPropertyInAstObject(tsCfgAst, 'compilerOptions'); + if (!compilerOptionsAstNode || compilerOptionsAstNode.kind != 'object') { + throw new SchematicsException( + 'Invalid root tsconfig "compilerOptions" property; expected an object.', + ); + } + + if ( + findPropertyInAstObject(compilerOptionsAstNode, 'baseUrl') && + findPropertyInAstObject(compilerOptionsAstNode, 'module') + ) { + return host; + } + + const compilerOptions = compilerOptionsAstNode.value; + const { baseUrl = './', module = 'es2015'} = compilerOptions; + + const validBaseUrl = ['./', '', '.']; + if (!validBaseUrl.includes(baseUrl as string)) { + const formattedBaseUrl = validBaseUrl.map(x => `'${x}'`).join(', '); + context.logger.warn(tags.oneLine + `Root tsconfig option 'baseUrl' is not one of: ${formattedBaseUrl}. + This might cause unexpected behaviour when generating libraries.`, + ); + } + + if (module !== 'es2015') { + context.logger.warn( + `Root tsconfig option 'module' is not 'es2015'. This might cause unexpected behaviour.`, + ); + } + + compilerOptions.module = module; + compilerOptions.baseUrl = baseUrl; + + host.overwrite(tsConfigPath, JSON.stringify(tsCfgAst.value, null, 2)); + + return host; + }; +} + export default function (): Rule { return (host: Tree, context: SchematicContext) => { if (host.exists('/.angular.json') || host.exists('/angular.json')) { @@ -748,6 +802,7 @@ export default function (): Rule { migrateConfiguration(config, context.logger), updateSpecTsConfig(config), updatePackageJson(config), + updateRootTsConfig(), updateTsLintConfig(), (host: Tree, context: SchematicContext) => { context.logger.warn(tags.oneLine`Some configuration options have been changed, diff --git a/packages/schematics/angular/migrations/update-6/index_spec.ts b/packages/schematics/angular/migrations/update-6/index_spec.ts index 12b430cb5ca4..d2627791ee08 100644 --- a/packages/schematics/angular/migrations/update-6/index_spec.ts +++ b/packages/schematics/angular/migrations/update-6/index_spec.ts @@ -775,6 +775,38 @@ describe('Migration to v6', () => { }); }); + describe('root ts config', () => { + const rootTsConfig = '/tsconfig.json'; + let compilerOptions: JsonObject; + + beforeEach(() => { + tree.create(rootTsConfig, ` + { + "compilerOptions": { + "noEmitOnError": true + } + } + `); + + tree.create(oldConfigPath, JSON.stringify(baseConfig, null, 2)); + tree = schematicRunner.runSchematic('migration-01', defaultOptions, tree); + const content = tree.readContent(rootTsConfig); + compilerOptions = JSON.parse(content).compilerOptions; + }); + + it('should add baseUrl', () => { + expect(compilerOptions.baseUrl).toEqual('./'); + }); + + it('should add module', () => { + expect(compilerOptions.module).toEqual('es2015'); + }); + + it('should not remove existing options', () => { + expect(compilerOptions.noEmitOnError).toBeDefined(); + }); + }); + describe('package.json', () => { it('should add a dev dependency to @angular-devkit/build-angular', () => { tree.create(oldConfigPath, JSON.stringify(baseConfig, null, 2));