Skip to content

Commit

Permalink
fix(@schematics/angular): resolve windows paths in tsconfig migration
Browse files Browse the repository at this point in the history
Fix #16800
  • Loading branch information
filipesilva authored and mgechev committed Feb 4, 2020
1 parent 085e011 commit d9119f6
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 9 deletions.
Expand Up @@ -7,14 +7,20 @@
*/
import { JsonAstObject, logging } from '@angular-devkit/core';
import { Rule, Tree, UpdateRecorder } from '@angular-devkit/schematics';
import { posix } from 'path';
import { dirname, relative } from 'path';
import {
findPropertyInAstObject,
insertPropertyInAstObjectInOrder,
removePropertyInAstObject,
} from '../../utility/json-utils';
import { Builders } from '../../utility/workspace-models';
import { getAllOptions, getTargets, getWorkspace, readJsonFileAsAstObject } from './utils';
import {
forwardSlashPath,
getAllOptions,
getTargets,
getWorkspace,
readJsonFileAsAstObject,
} from './utils';

/**
* Update the tsconfig files for applications
Expand Down Expand Up @@ -107,15 +113,18 @@ function updateTsConfig(tree: Tree, builderConfig: JsonAstObject, builderName: B
const files = findPropertyInAstObject(tsConfigAst, 'files');
if (!files) {
const newFiles: string[] = [];
const tsConfigDir = dirname(forwardSlashPath(tsConfigPath));

const mainOption = findPropertyInAstObject(option, 'main');
if (mainOption && mainOption.kind === 'string') {
newFiles.push(posix.relative(posix.dirname(tsConfigPath), mainOption.value));
newFiles.push(
forwardSlashPath(relative(tsConfigDir, forwardSlashPath(mainOption.value))));
}

const polyfillsOption = findPropertyInAstObject(option, 'polyfills');
if (polyfillsOption && polyfillsOption.kind === 'string') {
newFiles.push(posix.relative(posix.dirname(tsConfigPath), polyfillsOption.value));
newFiles.push(
forwardSlashPath(relative(tsConfigDir, forwardSlashPath(polyfillsOption.value))));
}

if (newFiles.length) {
Expand Down
Expand Up @@ -8,6 +8,7 @@

import { EmptyTree } from '@angular-devkit/schematics';
import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing';
import { getWorkspaceTargets, updateWorkspaceTargets } from './update-workspace-config_spec';

// tslint:disable-next-line: no-any
function overrideJsonFile(tree: UnitTestTree, path: string, newContent: object) {
Expand Down Expand Up @@ -64,6 +65,32 @@ describe('Migration to version 9', () => {
expect(files).toEqual(['src/main.ts', 'src/polyfills.ts']);
});

it('should resolve paths correctly even if they are using windows separators', async () => {
const tree2 = await schematicRunner
.runExternalSchematicAsync(
require.resolve('../../collection.json'),
'application',
{
name: 'another-app',
},
tree,
)
.toPromise();

const tsCfgPath = 'projects/another-app/tsconfig.app.json';
overrideJsonFile(tree2, tsCfgPath, defaultTsConfigOptions);
const config = getWorkspaceTargets(tree2, 'another-app');
config.build.options.main = 'projects\\another-app\\src\\main.ts';
config.build.options.polyfills = 'projects\\another-app\\src\\polyfills.ts';
config.build.options.tsConfig = 'projects\\another-app\\tsconfig.app.json';
updateWorkspaceTargets(tree2, config, 'another-app');

const tree3 = await schematicRunner.runSchematicAsync('workspace-version-9', {}, tree2.branch()).toPromise();
const { exclude, files } = JSON.parse(tree3.readContent(tsCfgPath));
expect(exclude).toBeUndefined();
expect(files).toEqual(['src/main.ts', 'src/polyfills.ts']);
});

it('should update apps tsConfig when tsconfig has include', async () => {
const tsConfigContent = {
...defaultTsConfigOptions,
Expand Down
Expand Up @@ -13,14 +13,17 @@ import { WorkspaceTargets } from '../../utility/workspace-models';
import { ANY_COMPONENT_STYLE_BUDGET } from './update-workspace-config';

// tslint:disable-next-line: no-any
function getWorkspaceTargets(tree: UnitTestTree): any {
return JSON.parse(tree.readContent(workspacePath))
.projects['migration-test'].architect;
export function getWorkspaceTargets(tree: UnitTestTree, project = 'migration-test'): any {
return JSON.parse(tree.readContent(workspacePath)).projects[project].architect;
}

function updateWorkspaceTargets(tree: UnitTestTree, workspaceTargets: WorkspaceTargets) {
export function updateWorkspaceTargets(
tree: UnitTestTree,
workspaceTargets: WorkspaceTargets,
project = 'migration-test',
) {
const config = JSON.parse(tree.readContent(workspacePath));
config.projects['migration-test'].architect = workspaceTargets;
config.projects[project].architect = workspaceTargets;
tree.overwrite(workspacePath, JSON.stringify(config, undefined, 2));
}

Expand Down
6 changes: 6 additions & 0 deletions packages/schematics/angular/migrations/update-9/utils.ts
Expand Up @@ -144,3 +144,9 @@ export function isIvyEnabled(tree: Tree, tsConfigPath: string): boolean {

return true;
}

// TS represents paths internally with '/' and expects paths to be in this format.
// angular.json expects paths with '/', but doesn't enforce them.
export function forwardSlashPath(path: string) {
return path.replace(/\\/g, '/');
}

0 comments on commit d9119f6

Please sign in to comment.