Skip to content

Commit

Permalink
fix(misc): support workspaces using a root tsconfig.json instead of t…
Browse files Browse the repository at this point in the history
…sconfig.base.json (#9195)

* fix(misc): support workspaces using a root tsconfig.json instead of tsconfig.base.json

* cleanup(angular): address pr feedback
  • Loading branch information
leosvelperez committed Mar 9, 2022
1 parent 16c6891 commit acc29e9
Show file tree
Hide file tree
Showing 81 changed files with 884 additions and 114 deletions.
9 changes: 8 additions & 1 deletion e2e/workspace-integrations/src/workspace.test.ts
Expand Up @@ -402,12 +402,19 @@ describe('affected:*', () => {
expect(affectedLibs).not.toContain(mylib2);

const implicitlyAffectedLibs = runCLI(
'affected:libs --files="tsconfig.json"'
'affected:libs --files="tsconfig.base.json"'
);
expect(implicitlyAffectedLibs).toContain(mypublishablelib);
expect(implicitlyAffectedLibs).toContain(mylib);
expect(implicitlyAffectedLibs).toContain(mylib2);

const noAffectedLibsNonExistentFile = runCLI(
'affected:libs --files="tsconfig.json"'
);
expect(noAffectedLibsNonExistentFile).not.toContain(mypublishablelib);
expect(noAffectedLibsNonExistentFile).not.toContain(mylib);
expect(noAffectedLibsNonExistentFile).not.toContain(mylib2);

const noAffectedLibs = runCLI('affected:libs --files="README.md"');
expect(noAffectedLibs).not.toContain(mypublishablelib);
expect(noAffectedLibs).not.toContain(mylib);
Expand Down
42 changes: 42 additions & 0 deletions packages/angular/src/generators/application/application.spec.ts
Expand Up @@ -185,6 +185,27 @@ describe('app', () => {
const workspaceJson = readJson(appTree, '/workspace.json');
expect(workspaceJson.projects['app'].projectType).toEqual('application');
});

it('should extend from tsconfig.base.json', async () => {
// ACT
await generateApp(appTree, 'app');

// ASSERT
const appTsConfig = readJson(appTree, 'apps/app/tsconfig.json');
expect(appTsConfig.extends).toBe('../../tsconfig.base.json');
});

it('should support a root tsconfig.json instead of tsconfig.base.json', async () => {
// ARRANGE
appTree.rename('tsconfig.base.json', 'tsconfig.json');

// ACT
await generateApp(appTree, 'app');

// ASSERT
const appTsConfig = readJson(appTree, 'apps/app/tsconfig.json');
expect(appTsConfig.extends).toBe('../../tsconfig.json');
});
});

describe('nested', () => {
Expand Down Expand Up @@ -258,6 +279,27 @@ describe('app', () => {
},
].forEach(hasJsonValue);
});

it('should extend from tsconfig.base.json', async () => {
// ACT
await generateApp(appTree, 'app', { directory: 'myDir' });

// ASSERT
const appTsConfig = readJson(appTree, 'apps/my-dir/app/tsconfig.json');
expect(appTsConfig.extends).toBe('../../../tsconfig.base.json');
});

it('should support a root tsconfig.json instead of tsconfig.base.json', async () => {
// ARRANGE
appTree.rename('tsconfig.base.json', 'tsconfig.json');

// ACT
await generateApp(appTree, 'app', { directory: 'myDir' });

// ASSERT
const appTsConfig = readJson(appTree, 'apps/my-dir/app/tsconfig.json');
expect(appTsConfig.extends).toBe('../../../tsconfig.json');
});
});

describe('at the root', () => {
Expand Down
@@ -1,5 +1,5 @@
{
"extends": "<%= offsetFromRoot %>tsconfig.base.json",
"extends": "<%= rootTsConfigPath %>",
"files": [],
"include": [],
"references": [
Expand Down
@@ -1,8 +1,8 @@
import type { Tree } from '@nrwl/devkit';
import { generateFiles, joinPathFragments } from '@nrwl/devkit';
import { getRelativePathToRootTsConfig } from '@nrwl/workspace/src/utilities/typescript';
import type { NormalizedSchema } from './normalized-schema';

import { generateFiles, joinPathFragments, offsetFromRoot } from '@nrwl/devkit';

export function createFiles(
host: Tree,
options: NormalizedSchema,
Expand All @@ -16,7 +16,10 @@ export function createFiles(
options.appProjectRoot,
{
...options,
offsetFromRoot: offsetFromRoot(options.appProjectRoot),
rootTsConfigPath: getRelativePathToRootTsConfig(
host,
options.appProjectRoot
),
tpl: '',
}
);
Expand Down
Expand Up @@ -6,6 +6,7 @@ import {
updateJson,
updateProjectConfiguration,
} from '@nrwl/devkit';
import { getRelativePathToRootTsConfig } from '@nrwl/workspace/src/utilities/typescript';
import type { NormalizedSchema } from './normalized-schema';

export function updateE2eProject(tree: Tree, options: NormalizedSchema) {
Expand Down Expand Up @@ -60,7 +61,7 @@ export function updateE2eProject(tree: Tree, options: NormalizedSchema) {
updateJson(tree, `${options.e2eProjectRoot}/tsconfig.json`, (json) => {
return {
...json,
extends: `${offsetFromRoot(options.e2eProjectRoot)}tsconfig.base.json`,
extends: getRelativePathToRootTsConfig(tree, options.e2eProjectRoot),
};
});
}
@@ -1,11 +1,12 @@
import { Tree, updateJson } from '@nrwl/devkit';
import { getRootTsConfigPathInTree } from '@nrwl/workspace/src/utilities/typescript';
import { NormalizedGeneratorOptions } from '../schema';

export function addPathMapping(
tree: Tree,
options: NormalizedGeneratorOptions
): void {
updateJson(tree, 'tsconfig.base.json', (json) => {
updateJson(tree, getRootTsConfigPathInTree(tree), (json) => {
const c = json.compilerOptions;
c.paths = c.paths || {};
c.paths[options.secondaryEntryPoint] = [
Expand Down
Expand Up @@ -123,6 +123,28 @@ describe('librarySecondaryEntryPoint generator', () => {
).toStrictEqual(['libs/lib1/testing/src/index.ts']);
});

it('should support a root tsconfig.json instead of tsconfig.base.json', async () => {
tree.rename('tsconfig.base.json', 'tsconfig.json');
addProjectConfiguration(tree, 'lib1', {
root: 'libs/lib1',
projectType: 'library',
});
tree.write(
'libs/lib1/package.json',
JSON.stringify({ name: '@my-org/lib1' })
);

await librarySecondaryEntryPointGenerator(tree, {
name: 'testing',
library: 'lib1',
});

const tsConfig = readJson(tree, 'tsconfig.json');
expect(
tsConfig.compilerOptions.paths['@my-org/lib1/testing']
).toStrictEqual(['libs/lib1/testing/src/index.ts']);
});

it('should add the entry point file patterns to the lint target', async () => {
addProjectConfiguration(tree, 'lib1', {
root: 'libs/lib1',
Expand Down
@@ -1,5 +1,5 @@
{
"extends": "<%= offsetFromRoot %>tsconfig.base.json",
"extends": "<%= rootTsConfigPath %>",
"files": [],
"include": [],
"references": [
Expand Down
12 changes: 8 additions & 4 deletions packages/angular/src/generators/library/lib/update-project.ts
@@ -1,14 +1,15 @@
import {
generateFiles,
getWorkspaceLayout,
joinPathFragments,
offsetFromRoot,
readProjectConfiguration,
Tree,
updateJson,
updateProjectConfiguration,
getWorkspaceLayout,
offsetFromRoot,
joinPathFragments,
} from '@nrwl/devkit';
import { replaceAppNameWithPath } from '@nrwl/workspace';
import { getRelativePathToRootTsConfig } from '@nrwl/workspace/src/utilities/typescript';
import * as path from 'path';
import { NormalizedSchema } from './normalized-schema';
import { updateNgPackage } from './update-ng-package';
Expand Down Expand Up @@ -118,7 +119,10 @@ function createFiles(host: Tree, options: NormalizedSchema) {
options.projectRoot,
{
...options,
offsetFromRoot: offsetFromRoot(options.projectRoot),
rootTsConfigPath: getRelativePathToRootTsConfig(
host,
options.projectRoot
),
tpl: '',
}
);
Expand Down
Expand Up @@ -4,10 +4,11 @@ import {
Tree,
updateJson,
} from '@nrwl/devkit';
import { getRootTsConfigPathInTree } from '@nrwl/workspace/src/utilities/typescript';
import { NormalizedSchema } from './normalized-schema';

function updateRootConfig(host: Tree, options: NormalizedSchema) {
updateJson(host, 'tsconfig.base.json', (json) => {
updateJson(host, getRootTsConfigPathInTree(host), (json) => {
const c = json.compilerOptions;
c.paths = c.paths || {};
delete c.paths[options.name];
Expand Down
24 changes: 24 additions & 0 deletions packages/angular/src/generators/library/library.spec.ts
Expand Up @@ -305,6 +305,18 @@ describe('lib', () => {
});
});

it('should support a root tsconfig.json instead of tsconfig.base.json', async () => {
// ARRANGE
tree.rename('tsconfig.base.json', 'tsconfig.json');

// ACT
await runLibraryGeneratorWithOpts();

// ASSERT
const appTsConfig = readJson(tree, 'libs/my-lib/tsconfig.json');
expect(appTsConfig.extends).toBe('../../tsconfig.json');
});

it('should check for existence of spec files before deleting them', async () => {
// ARRANGE
updateJson<NxJsonConfiguration, NxJsonConfiguration>(
Expand Down Expand Up @@ -633,6 +645,18 @@ describe('lib', () => {
],
});
});

it('should support a root tsconfig.json instead of tsconfig.base.json', async () => {
// ARRANGE
tree.rename('tsconfig.base.json', 'tsconfig.json');

// ACT
await runLibraryGeneratorWithOpts({ directory: 'myDir' });

// ASSERT
const appTsConfig = readJson(tree, 'libs/my-dir/my-lib/tsconfig.json');
expect(appTsConfig.extends).toBe('../../../tsconfig.json');
});
});

describe('at the root', () => {
Expand Down
Expand Up @@ -12,7 +12,7 @@ const share = mf.share;
* This NX_TSCONFIG_PATH environment variable is set by the @nrwl/angular:webpack-browser and it contains
* the location of the generated temporary tsconfig file.
*/
const tsConfigPath = process.env.NX_TSCONFIG_PATH ?? path.join(__dirname, '<%= offsetFromRoot %>tsconfig.base.json');
const tsConfigPath = process.env.NX_TSCONFIG_PATH ?? path.join(__dirname, '<%= rootTsConfigPath %>');

const workspaceRootPath = path.join(__dirname, '<%= offsetFromRoot %>');
const sharedMappings = new mf.SharedMappings();
Expand Down
@@ -1,11 +1,12 @@
import type { Tree } from '@nrwl/devkit';
import type { Schema } from '../schema';
import {
generateFiles,
joinPathFragments,
logger,
offsetFromRoot,
} from '@nrwl/devkit';
import { getRelativePathToRootTsConfig } from '@nrwl/workspace/src/utilities/typescript';
import type { Schema } from '../schema';

const SHARED_SINGLETON_LIBRARIES = [
'@angular/core',
Expand All @@ -30,6 +31,7 @@ export function generateWebpackConfig(
If this was not the outcome you expected, you can discard the changes we have made, create a backup of your current webpack config, and run the command again.`
);
}

generateFiles(
host,
joinPathFragments(__dirname, '../files/webpack'),
Expand All @@ -42,6 +44,7 @@ export function generateWebpackConfig(
sourceRoot: appRoot,
sharedLibraries: SHARED_SINGLETON_LIBRARIES,
offsetFromRoot: offsetFromRoot(appRoot),
rootTsConfigPath: getRelativePathToRootTsConfig(host, appRoot),
}
);
}
29 changes: 29 additions & 0 deletions packages/angular/src/generators/setup-mfe/setup-mfe.spec.ts
Expand Up @@ -43,6 +43,35 @@ describe('Init MFE', () => {
}
);

test.each([
['app1', 'host'],
['remote1', 'remote'],
])(
'should support a root tsconfig.json instead of tsconfig.base.json',
async (app, type: 'host' | 'remote') => {
// ARRANGE
host.rename('tsconfig.base.json', 'tsconfig.json');

// ACT
await setupMfe(host, {
appName: app,
mfeType: type,
});

// ASSERT
expect(host.exists(`apps/${app}/webpack.config.js`)).toBeTruthy();
expect(host.exists(`apps/${app}/webpack.prod.config.js`)).toBeTruthy();

const webpackContents = host.read(
`apps/${app}/webpack.config.js`,
'utf-8'
);
expect(webpackContents).toContain(
"const tsConfigPath = process.env.NX_TSCONFIG_PATH ?? path.join(__dirname, '../../tsconfig.json');"
);
}
);

test.each([
['app1', 'host'],
['remote1', 'remote'],
Expand Down
@@ -1,21 +1,16 @@
import type { Tree } from '@nrwl/devkit';
import {
getWorkspaceLayout,
joinPathFragments,
offsetFromRoot,
readProjectConfiguration,
updateJson,
} from '@nrwl/devkit';
import { getRelativePathToRootTsConfig } from '@nrwl/workspace/src/utilities/typescript';

export function updateTsConfig(tree: Tree, project: string): void {
const workerTsConfigPath = joinPathFragments(
getWorkspaceLayout(tree).appsDir,
project,
'tsconfig.worker.json'
);
const { root } = readProjectConfiguration(tree, project);
const workerTsConfigPath = joinPathFragments(root, 'tsconfig.worker.json');
updateJson(tree, workerTsConfigPath, (json) => {
json.extends = `${offsetFromRoot(root)}tsconfig.base.json`;
json.extends = getRelativePathToRootTsConfig(tree, root);
return json;
});
}
10 changes: 10 additions & 0 deletions packages/angular/src/generators/web-worker/web-worker.spec.ts
Expand Up @@ -29,6 +29,16 @@ describe('webWorker generator', () => {
).toContain('"extends": "../../tsconfig.base.json"');
});

it('should extend from tsconfig.json when used instead of tsconfig.base.json', async () => {
tree.rename('tsconfig.base.json', 'tsconfig.json');

await webWorkerGenerator(tree, { name: 'test-worker', project: appName });

expect(
tree.read(`apps/${appName}/tsconfig.worker.json`, 'utf-8')
).toContain('"extends": "../../tsconfig.json"');
});

it('should format files', async () => {
jest.spyOn(devkit, 'formatFiles');

Expand Down

0 comments on commit acc29e9

Please sign in to comment.