Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 2 commits into from Mar 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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