feat(misc): do not generate tsconfig.base.json for simple standalone … (#13605)
This commit is contained in:
parent
eb3242ab44
commit
91c19f5c0a
18
.editorconfig
Normal file
18
.editorconfig
Normal file
@ -0,0 +1,18 @@
|
||||
# EditorConfig is awesome: https://EditorConfig.org
|
||||
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
# Unix-style newlines with a newline ending every file
|
||||
[*]
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
|
||||
# 4 space indentation
|
||||
[*.{js,ts,jsx,tsx}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[package.json]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
@ -1,10 +0,0 @@
|
||||
{
|
||||
"extends": "<%= rootTsConfigPath %>",
|
||||
"files": [],
|
||||
"include": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.app.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -10,10 +10,6 @@ export function createFiles(tree: Tree, options: NormalizedSchema) {
|
||||
options.appProjectRoot,
|
||||
{
|
||||
...options,
|
||||
rootTsConfigPath: getRelativePathToRootTsConfig(
|
||||
tree,
|
||||
options.appProjectRoot
|
||||
),
|
||||
tpl: '',
|
||||
}
|
||||
);
|
||||
|
||||
@ -11,8 +11,16 @@ import {
|
||||
import { replaceAppNameWithPath } from '@nrwl/workspace/src/utils/cli-config-utils';
|
||||
import { E2eTestRunner, UnitTestRunner } from '../../../../utils/test-runners';
|
||||
import type { NormalizedSchema } from './normalized-schema';
|
||||
import {
|
||||
createTsConfig,
|
||||
extractTsConfigBase,
|
||||
} from '../../../utils/create-ts-config';
|
||||
import { getRelativePathToRootTsConfig } from '@nrwl/workspace/src/utilities/typescript';
|
||||
|
||||
export function updateConfigFiles(host: Tree, options: NormalizedSchema) {
|
||||
if (!options.rootProject) {
|
||||
extractTsConfigBase(host);
|
||||
}
|
||||
updateTsConfigOptions(host, options);
|
||||
updateAppAndE2EProjectConfigurations(host, options);
|
||||
}
|
||||
@ -36,14 +44,13 @@ function updateTsConfigOptions(host: Tree, options: NormalizedSchema) {
|
||||
],
|
||||
}));
|
||||
|
||||
// tsconfig.json
|
||||
updateJson(host, `${options.appProjectRoot}/tsconfig.json`, (json) => ({
|
||||
...json,
|
||||
compilerOptions: {
|
||||
...json.compilerOptions,
|
||||
target: 'es2020',
|
||||
},
|
||||
}));
|
||||
createTsConfig(
|
||||
host,
|
||||
options.appProjectRoot,
|
||||
'app',
|
||||
options,
|
||||
getRelativePathToRootTsConfig(host, options.appProjectRoot)
|
||||
);
|
||||
}
|
||||
|
||||
function updateAppAndE2EProjectConfigurations(
|
||||
|
||||
@ -1073,9 +1073,7 @@ describe('app', () => {
|
||||
expect(appTree.exists('src/app/app.module.ts')).toBe(true);
|
||||
expect(appTree.exists('src/app/app.component.ts')).toBe(true);
|
||||
expect(appTree.exists('e2e/cypress.config.ts')).toBe(true);
|
||||
expect(readJson(appTree, 'tsconfig.json').extends).toEqual(
|
||||
'./tsconfig.base.json'
|
||||
);
|
||||
expect(readJson(appTree, 'tsconfig.json').extends).toBeUndefined();
|
||||
const project = readProjectConfiguration(appTree, 'my-app');
|
||||
expect(project.targets.build.options['outputPath']).toBe('dist/my-app');
|
||||
});
|
||||
|
||||
@ -214,18 +214,6 @@ describe('app', () => {
|
||||
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');
|
||||
});
|
||||
|
||||
it('should set default project', async () => {
|
||||
// ACT
|
||||
await generateApp(appTree);
|
||||
@ -339,18 +327,6 @@ describe('app', () => {
|
||||
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', () => {
|
||||
|
||||
@ -1,10 +0,0 @@
|
||||
{
|
||||
"extends": "<%= rootTsConfigPath %>",
|
||||
"files": [],
|
||||
"include": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.app.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -11,6 +11,8 @@ import {
|
||||
import { replaceAppNameWithPath } from '@nrwl/workspace/src/utils/cli-config-utils';
|
||||
import { E2eTestRunner, UnitTestRunner } from '../../../utils/test-runners';
|
||||
import type { NormalizedSchema } from './normalized-schema';
|
||||
import { createTsConfig } from '../../utils/create-ts-config';
|
||||
import { getRelativePathToRootTsConfig } from '@nrwl/workspace/src/utilities/typescript';
|
||||
|
||||
export function updateConfigFiles(host: Tree, options: NormalizedSchema) {
|
||||
updateTsConfigOptions(host, options);
|
||||
@ -37,14 +39,13 @@ function updateTsConfigOptions(host: Tree, options: NormalizedSchema) {
|
||||
}));
|
||||
|
||||
// tsconfig.json
|
||||
updateJson(host, `${options.appProjectRoot}/tsconfig.json`, (json) => ({
|
||||
...json,
|
||||
compilerOptions: {
|
||||
...json.compilerOptions,
|
||||
target: 'es2022',
|
||||
useDefineForClassFields: false, // This will eventually need updated when Angular switch to using TC39 Compliant code
|
||||
},
|
||||
}));
|
||||
createTsConfig(
|
||||
host,
|
||||
options.appProjectRoot,
|
||||
'app',
|
||||
options,
|
||||
getRelativePathToRootTsConfig(host, options.appProjectRoot)
|
||||
);
|
||||
}
|
||||
|
||||
function updateAppAndE2EProjectConfigurations(
|
||||
|
||||
@ -1,14 +0,0 @@
|
||||
{
|
||||
"extends": "<%= rootTsConfigPath %>",
|
||||
"files": [],
|
||||
"include": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.lib.json"
|
||||
}<% if (publishable) { %>,
|
||||
{
|
||||
"path": "./tsconfig.lib.prod.json"
|
||||
}
|
||||
<% } %>
|
||||
]
|
||||
}
|
||||
@ -1,7 +1,14 @@
|
||||
import type { Tree } from '@nrwl/devkit';
|
||||
import { joinPathFragments, updateJson } from '@nrwl/devkit';
|
||||
import { getRootTsConfigPathInTree } from '@nrwl/workspace/src/utilities/typescript';
|
||||
import {
|
||||
getRelativePathToRootTsConfig,
|
||||
getRootTsConfigPathInTree,
|
||||
} from '@nrwl/workspace/src/utilities/typescript';
|
||||
import { NormalizedSchema } from './normalized-schema';
|
||||
import {
|
||||
createTsConfig,
|
||||
extractTsConfigBase,
|
||||
} from '../../utils/create-ts-config';
|
||||
|
||||
function updateRootConfig(
|
||||
host: Tree,
|
||||
@ -44,14 +51,13 @@ function updateProjectConfig(
|
||||
});
|
||||
|
||||
// tsconfig.json
|
||||
updateJson(host, `${options.projectRoot}/tsconfig.json`, (json) => ({
|
||||
...json,
|
||||
compilerOptions: {
|
||||
...json.compilerOptions,
|
||||
target: 'es2022',
|
||||
useDefineForClassFields: false,
|
||||
},
|
||||
}));
|
||||
createTsConfig(
|
||||
host,
|
||||
options.projectRoot,
|
||||
'lib',
|
||||
options,
|
||||
getRelativePathToRootTsConfig(host, options.projectRoot)
|
||||
);
|
||||
}
|
||||
|
||||
function updateProjectIvyConfig(
|
||||
@ -75,6 +81,7 @@ export function updateTsConfig(
|
||||
host: Tree,
|
||||
options: NormalizedSchema['libraryOptions']
|
||||
) {
|
||||
extractTsConfigBase(host);
|
||||
updateRootConfig(host, options);
|
||||
updateProjectConfig(host, options);
|
||||
updateProjectIvyConfig(host, options);
|
||||
|
||||
@ -313,16 +313,13 @@ describe('lib', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should support a root tsconfig.json instead of tsconfig.base.json', async () => {
|
||||
// ARRANGE
|
||||
it('should create tsconfig.base.json when it is missing', async () => {
|
||||
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');
|
||||
expect(appTsConfig.extends).toBe('../../tsconfig.base.json');
|
||||
});
|
||||
|
||||
it('should check for existence of spec files before deleting them', async () => {
|
||||
@ -663,56 +660,6 @@ describe('lib', () => {
|
||||
tsconfigJson.compilerOptions.paths['my-dir-my-lib/*']
|
||||
).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should create a local tsconfig.json', async () => {
|
||||
// ACT
|
||||
await runLibraryGeneratorWithOpts({ directory: 'myDir' });
|
||||
|
||||
// ASSERT
|
||||
const tsconfigJson = readJson(tree, 'libs/my-dir/my-lib/tsconfig.json');
|
||||
|
||||
expect(tsconfigJson).toEqual({
|
||||
extends: '../../../tsconfig.base.json',
|
||||
angularCompilerOptions: {
|
||||
enableI18nLegacyMessageIdFormat: false,
|
||||
strictInjectionParameters: true,
|
||||
strictInputAccessModifiers: true,
|
||||
strictTemplates: true,
|
||||
},
|
||||
compilerOptions: {
|
||||
forceConsistentCasingInFileNames: true,
|
||||
noFallthroughCasesInSwitch: true,
|
||||
noPropertyAccessFromIndexSignature: true,
|
||||
noImplicitOverride: true,
|
||||
noImplicitReturns: true,
|
||||
strict: true,
|
||||
target: 'es2022',
|
||||
useDefineForClassFields: false,
|
||||
},
|
||||
files: [],
|
||||
include: [],
|
||||
references: [
|
||||
{
|
||||
path: './tsconfig.lib.json',
|
||||
},
|
||||
{
|
||||
path: './tsconfig.spec.json',
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
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', () => {
|
||||
|
||||
42
packages/angular/src/generators/utils/create-ts-config.ts
Normal file
42
packages/angular/src/generators/utils/create-ts-config.ts
Normal file
@ -0,0 +1,42 @@
|
||||
import { Tree } from 'nx/src/generators/tree';
|
||||
import { tsConfigBaseOptions } from '@nrwl/workspace/src/utils/create-ts-config';
|
||||
import { writeJson } from 'nx/src/generators/utils/json';
|
||||
export { extractTsConfigBase } from '@nrwl/workspace/src/utils/create-ts-config';
|
||||
|
||||
export function createTsConfig(
|
||||
host: Tree,
|
||||
projectRoot: string,
|
||||
type: 'app' | 'lib',
|
||||
options: {
|
||||
strict?: boolean;
|
||||
style?: string;
|
||||
bundler?: string;
|
||||
rootProject?: boolean;
|
||||
},
|
||||
relativePathToRootTsConfig: string
|
||||
) {
|
||||
const json = {
|
||||
compilerOptions: {
|
||||
target: 'es2022',
|
||||
useDefineForClassFields: false,
|
||||
},
|
||||
files: [],
|
||||
include: [],
|
||||
references: [
|
||||
{
|
||||
path: type === 'app' ? './tsconfig.app.json' : './tsconfig.lib.json',
|
||||
},
|
||||
],
|
||||
} as any;
|
||||
|
||||
// inline tsconfig.base.json into the project
|
||||
if (options.rootProject) {
|
||||
json.compileOnSave = false;
|
||||
json.compilerOptions = { ...tsConfigBaseOptions, ...json.compilerOptions };
|
||||
json.exclude = ['node_modules', 'tmp'];
|
||||
} else {
|
||||
json.extends = relativePathToRootTsConfig;
|
||||
}
|
||||
|
||||
writeJson(host, `${projectRoot}/tsconfig.json`, json);
|
||||
}
|
||||
@ -104,17 +104,7 @@ describe('app', () => {
|
||||
path: './tsconfig.spec.json',
|
||||
},
|
||||
]);
|
||||
expect(tsconfig.compilerOptions.forceConsistentCasingInFileNames).toEqual(
|
||||
true
|
||||
);
|
||||
expect(tsconfig.compilerOptions.strict).toEqual(true);
|
||||
expect(tsconfig.compilerOptions.noImplicitOverride).toEqual(true);
|
||||
expect(
|
||||
tsconfig.compilerOptions.noPropertyAccessFromIndexSignature
|
||||
).toEqual(true);
|
||||
expect(tsconfig.compilerOptions.noImplicitReturns).toEqual(true);
|
||||
expect(tsconfig.compilerOptions.noFallthroughCasesInSwitch).toEqual(true);
|
||||
|
||||
const tsconfigApp = readJson(appTree, 'apps/my-app/tsconfig.app.json');
|
||||
expect(tsconfigApp.compilerOptions.outDir).toEqual('../../dist/out-tsc');
|
||||
expect(tsconfigApp.extends).toEqual('./tsconfig.json');
|
||||
@ -165,15 +155,6 @@ describe('app', () => {
|
||||
const tsConfig = readJson(appTree, 'apps/my-app/tsconfig.json');
|
||||
expect(tsConfig.extends).toEqual('../../tsconfig.base.json');
|
||||
});
|
||||
|
||||
it('should extend from root tsconfig.json when no tsconfig.base.json', async () => {
|
||||
appTree.rename('tsconfig.base.json', 'tsconfig.json');
|
||||
|
||||
await applicationGenerator(appTree, schema);
|
||||
|
||||
const tsConfig = readJson(appTree, 'apps/my-app/tsconfig.json');
|
||||
expect(tsConfig.extends).toEqual('../../tsconfig.json');
|
||||
});
|
||||
});
|
||||
|
||||
describe('nested', () => {
|
||||
@ -902,15 +883,7 @@ describe('app', () => {
|
||||
expect(
|
||||
tsconfigJson.compilerOptions.forceConsistentCasingInFileNames
|
||||
).not.toBeDefined();
|
||||
expect(tsconfigJson.compilerOptions.strict).not.toBeDefined();
|
||||
expect(tsconfigJson.compilerOptions.noImplicitOverride).not.toBeDefined();
|
||||
expect(
|
||||
tsconfigJson.compilerOptions.noPropertyAccessFromIndexSignature
|
||||
).not.toBeDefined();
|
||||
expect(tsconfigJson.compilerOptions.noImplicitReturns).not.toBeDefined();
|
||||
expect(
|
||||
tsconfigJson.compilerOptions.noFallthroughCasesInSwitch
|
||||
).not.toBeDefined();
|
||||
expect(tsconfigJson.compilerOptions.strict).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
@ -931,24 +904,6 @@ describe('app', () => {
|
||||
|
||||
describe('--root-project', () => {
|
||||
it('should create files at the root', async () => {
|
||||
await applicationGenerator(appTree, {
|
||||
...schema,
|
||||
rootProject: true,
|
||||
bundler: 'webpack',
|
||||
});
|
||||
expect(appTree.read('/src/main.tsx')).toBeDefined();
|
||||
expect(appTree.read('/e2e/cypress.config.ts')).toBeDefined();
|
||||
expect(readJson(appTree, '/tsconfig.json').extends).toEqual(
|
||||
'./tsconfig.base.json'
|
||||
);
|
||||
expect(
|
||||
readJson(appTree, '/workspace.json').projects['my-app'].architect[
|
||||
'build'
|
||||
].options['outputPath']
|
||||
).toEqual('dist/my-app');
|
||||
});
|
||||
|
||||
it('should create files at the root if bundler is vite', async () => {
|
||||
await applicationGenerator(appTree, {
|
||||
...schema,
|
||||
name: 'my-app2',
|
||||
@ -957,9 +912,11 @@ describe('app', () => {
|
||||
});
|
||||
expect(appTree.read('/src/main.tsx')).toBeDefined();
|
||||
expect(appTree.read('/e2e/cypress.config.ts')).toBeDefined();
|
||||
expect(readJson(appTree, '/tsconfig.json').extends).toEqual(
|
||||
'./tsconfig.base.json'
|
||||
);
|
||||
|
||||
const rootTsConfig = readJson(appTree, '/tsconfig.json');
|
||||
expect(rootTsConfig.extends).toBeUndefined();
|
||||
expect(rootTsConfig.compilerOptions.sourceMap).toBe(true);
|
||||
|
||||
expect(
|
||||
readJson(appTree, '/workspace.json').projects['my-app2'].architect[
|
||||
'build'
|
||||
|
||||
@ -32,6 +32,7 @@ import {
|
||||
swcLoaderVersion,
|
||||
} from '../../utils/versions';
|
||||
import { installCommonDependencies } from './lib/install-common-dependencies';
|
||||
import { extractTsConfigBase } from '../../utils/create-ts-config';
|
||||
|
||||
async function addLinting(host: Tree, options: NormalizedSchema) {
|
||||
const tasks: GeneratorCallback[] = [];
|
||||
@ -90,6 +91,10 @@ export async function applicationGenerator(host: Tree, schema: Schema) {
|
||||
|
||||
tasks.push(initTask);
|
||||
|
||||
if (!options.rootProject) {
|
||||
extractTsConfigBase(host);
|
||||
}
|
||||
|
||||
createApplicationFiles(host, options);
|
||||
addProject(host, options);
|
||||
|
||||
|
||||
@ -1,29 +0,0 @@
|
||||
{
|
||||
"extends": "<%= rootTsConfigPath %>",
|
||||
"compilerOptions": {
|
||||
"jsx": "react-jsx",
|
||||
<% if (style === '@emotion/styled') { %>"jsxImportSource": "@emotion/react",<% } %>
|
||||
"allowJs": false,
|
||||
"esModuleInterop": false,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"isolatedModules": true,
|
||||
"lib": ["DOM", "DOM.Iterable", "ESNext"],
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Node",
|
||||
"noEmit": true,
|
||||
"resolveJsonModule": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
"target": "ESNext",
|
||||
"types": ["vite/client"],
|
||||
"useDefineForClassFields": true
|
||||
},
|
||||
"files": [],
|
||||
"include": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.app.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -1,17 +0,0 @@
|
||||
{
|
||||
"extends": "<%= rootTsConfigPath %>",
|
||||
"compilerOptions": {
|
||||
"jsx": "react-jsx",
|
||||
<% if (style === '@emotion/styled') { %>"jsxImportSource": "@emotion/react",<% } %>
|
||||
"allowJs": true,
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true
|
||||
},
|
||||
"files": [],
|
||||
"include": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.app.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -10,28 +10,7 @@ import {
|
||||
} from '@nrwl/devkit';
|
||||
import { join } from 'path';
|
||||
import { getRelativePathToRootTsConfig } from '@nrwl/workspace/src/utilities/typescript';
|
||||
|
||||
function updateTsConfig(host: Tree, options: NormalizedSchema) {
|
||||
updateJson(
|
||||
host,
|
||||
joinPathFragments(options.appProjectRoot, 'tsconfig.json'),
|
||||
(json) => {
|
||||
if (options.strict) {
|
||||
json.compilerOptions = {
|
||||
...json.compilerOptions,
|
||||
forceConsistentCasingInFileNames: true,
|
||||
strict: true,
|
||||
noImplicitOverride: true,
|
||||
noPropertyAccessFromIndexSignature: true,
|
||||
noImplicitReturns: true,
|
||||
noFallthroughCasesInSwitch: true,
|
||||
};
|
||||
}
|
||||
|
||||
return json;
|
||||
}
|
||||
);
|
||||
}
|
||||
import { createTsConfig } from '../../../utils/create-ts-config';
|
||||
|
||||
export function createApplicationFiles(host: Tree, options: NormalizedSchema) {
|
||||
let styleSolutionSpecificAppFiles: string;
|
||||
@ -47,15 +26,15 @@ export function createApplicationFiles(host: Tree, options: NormalizedSchema) {
|
||||
styleSolutionSpecificAppFiles = '../files/css-module';
|
||||
}
|
||||
|
||||
const relativePathToRootTsConfig = getRelativePathToRootTsConfig(
|
||||
host,
|
||||
options.appProjectRoot
|
||||
);
|
||||
const templateVariables = {
|
||||
...names(options.name),
|
||||
...options,
|
||||
tmpl: '',
|
||||
offsetFromRoot: offsetFromRoot(options.appProjectRoot),
|
||||
rootTsConfigPath: getRelativePathToRootTsConfig(
|
||||
host,
|
||||
options.appProjectRoot
|
||||
),
|
||||
};
|
||||
|
||||
generateFiles(
|
||||
@ -99,5 +78,11 @@ export function createApplicationFiles(host: Tree, options: NormalizedSchema) {
|
||||
toJS(host);
|
||||
}
|
||||
|
||||
updateTsConfig(host, options);
|
||||
createTsConfig(
|
||||
host,
|
||||
options.appProjectRoot,
|
||||
'app',
|
||||
options,
|
||||
relativePathToRootTsConfig
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,17 +0,0 @@
|
||||
{
|
||||
"extends": "<%= rootTsConfigPath %>",
|
||||
"compilerOptions": {
|
||||
"jsx": "react-jsx",
|
||||
<% if (style === '@emotion/styled') { %>"jsxImportSource": "@emotion/react",<% } %>
|
||||
"allowJs": true,
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true
|
||||
},
|
||||
"files": [],
|
||||
"include": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.lib.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -10,14 +10,18 @@ import {
|
||||
import { getRelativePathToRootTsConfig } from '@nrwl/workspace/src/utilities/typescript';
|
||||
|
||||
import { NormalizedSchema } from '../schema';
|
||||
import { createTsConfig } from '../../../utils/create-ts-config';
|
||||
|
||||
export function createFiles(host: Tree, options: NormalizedSchema) {
|
||||
const relativePathToRootTsConfig = getRelativePathToRootTsConfig(
|
||||
host,
|
||||
options.projectRoot
|
||||
);
|
||||
const substitutions = {
|
||||
...options,
|
||||
...names(options.name),
|
||||
tmpl: '',
|
||||
offsetFromRoot: offsetFromRoot(options.projectRoot),
|
||||
rootTsConfigPath: getRelativePathToRootTsConfig(host, options.projectRoot),
|
||||
};
|
||||
|
||||
generateFiles(
|
||||
@ -48,27 +52,11 @@ export function createFiles(host: Tree, options: NormalizedSchema) {
|
||||
toJS(host);
|
||||
}
|
||||
|
||||
updateTsConfig(host, options);
|
||||
}
|
||||
|
||||
function updateTsConfig(tree: Tree, options: NormalizedSchema) {
|
||||
updateJson(
|
||||
tree,
|
||||
joinPathFragments(options.projectRoot, 'tsconfig.json'),
|
||||
(json) => {
|
||||
if (options.strict) {
|
||||
json.compilerOptions = {
|
||||
...json.compilerOptions,
|
||||
forceConsistentCasingInFileNames: true,
|
||||
strict: true,
|
||||
noImplicitOverride: true,
|
||||
noPropertyAccessFromIndexSignature: true,
|
||||
noImplicitReturns: true,
|
||||
noFallthroughCasesInSwitch: true,
|
||||
};
|
||||
}
|
||||
|
||||
return json;
|
||||
}
|
||||
createTsConfig(
|
||||
host,
|
||||
options.projectRoot,
|
||||
'lib',
|
||||
options,
|
||||
relativePathToRootTsConfig
|
||||
);
|
||||
}
|
||||
|
||||
@ -96,12 +96,12 @@ describe('lib', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it('should update root tsconfig.json when no tsconfig.base.json', async () => {
|
||||
it('should create tsconfig.base.json out of tsconfig.json', async () => {
|
||||
tree.rename('tsconfig.base.json', 'tsconfig.json');
|
||||
|
||||
await libraryGenerator(tree, defaultSchema);
|
||||
|
||||
const tsconfigJson = readJson(tree, '/tsconfig.json');
|
||||
const tsconfigJson = readJson(tree, '/tsconfig.base.json');
|
||||
expect(tsconfigJson.compilerOptions.paths['@proj/my-lib']).toEqual([
|
||||
'libs/my-lib/src/index.ts',
|
||||
]);
|
||||
@ -133,27 +133,7 @@ describe('lib', () => {
|
||||
path: './tsconfig.spec.json',
|
||||
},
|
||||
]);
|
||||
expect(
|
||||
tsconfigJson.compilerOptions.forceConsistentCasingInFileNames
|
||||
).toEqual(true);
|
||||
expect(tsconfigJson.compilerOptions.strict).toEqual(true);
|
||||
expect(tsconfigJson.compilerOptions.noImplicitOverride).toEqual(true);
|
||||
expect(
|
||||
tsconfigJson.compilerOptions.noPropertyAccessFromIndexSignature
|
||||
).toEqual(true);
|
||||
expect(tsconfigJson.compilerOptions.noImplicitReturns).toEqual(true);
|
||||
expect(tsconfigJson.compilerOptions.noFallthroughCasesInSwitch).toEqual(
|
||||
true
|
||||
);
|
||||
});
|
||||
|
||||
it('should extend from root tsconfig.json when no tsconfig.base.json', async () => {
|
||||
tree.rename('tsconfig.base.json', 'tsconfig.json');
|
||||
|
||||
await libraryGenerator(tree, defaultSchema);
|
||||
|
||||
const tsconfigJson = readJson(tree, 'libs/my-lib/tsconfig.json');
|
||||
expect(tsconfigJson.extends).toBe('../../tsconfig.json');
|
||||
});
|
||||
|
||||
it('should extend the local tsconfig.json with tsconfig.spec.json', async () => {
|
||||
@ -325,20 +305,6 @@ describe('lib', () => {
|
||||
).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should update root tsconfig.json when no tsconfig.base.json', async () => {
|
||||
tree.rename('tsconfig.base.json', 'tsconfig.json');
|
||||
|
||||
await libraryGenerator(tree, { ...defaultSchema, directory: 'myDir' });
|
||||
|
||||
const tsconfigJson = readJson(tree, '/tsconfig.json');
|
||||
expect(tsconfigJson.compilerOptions.paths['@proj/my-dir/my-lib']).toEqual(
|
||||
['libs/my-dir/my-lib/src/index.ts']
|
||||
);
|
||||
expect(
|
||||
tsconfigJson.compilerOptions.paths['my-dir-my-lib/*']
|
||||
).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should create a local tsconfig.json', async () => {
|
||||
await libraryGenerator(tree, { ...defaultSchema, directory: 'myDir' });
|
||||
|
||||
@ -353,15 +319,6 @@ describe('lib', () => {
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('should extend from root tsconfig.json when no tsconfig.base.json', async () => {
|
||||
tree.rename('tsconfig.base.json', 'tsconfig.json');
|
||||
|
||||
await libraryGenerator(tree, { ...defaultSchema, directory: 'myDir' });
|
||||
|
||||
const tsconfigJson = readJson(tree, 'libs/my-dir/my-lib/tsconfig.json');
|
||||
expect(tsconfigJson.extends).toBe('../../../tsconfig.json');
|
||||
});
|
||||
});
|
||||
|
||||
describe('--style scss', () => {
|
||||
@ -704,18 +661,7 @@ describe('lib', () => {
|
||||
});
|
||||
const tsconfigJson = readJson(tree, '/libs/my-lib/tsconfig.json');
|
||||
|
||||
expect(
|
||||
tsconfigJson.compilerOptions.forceConsistentCasingInFileNames
|
||||
).not.toBeDefined();
|
||||
expect(tsconfigJson.compilerOptions.strict).not.toBeDefined();
|
||||
expect(tsconfigJson.compilerOptions.noImplicitOverride).not.toBeDefined();
|
||||
expect(
|
||||
tsconfigJson.compilerOptions.noPropertyAccessFromIndexSignature
|
||||
).not.toBeDefined();
|
||||
expect(tsconfigJson.compilerOptions.noImplicitReturns).not.toBeDefined();
|
||||
expect(
|
||||
tsconfigJson.compilerOptions.noFallthroughCasesInSwitch
|
||||
).not.toBeDefined();
|
||||
expect(tsconfigJson.compilerOptions.strict).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@ -21,6 +21,7 @@ import { addLinting } from './lib/add-linting';
|
||||
import { updateAppRoutes } from './lib/update-app-routes';
|
||||
import { createFiles } from './lib/create-files';
|
||||
import { updateBaseTsConfig } from './lib/update-base-tsconfig';
|
||||
import { extractTsConfigBase } from '../../utils/create-ts-config';
|
||||
import { installCommonDependencies } from './lib/install-common-dependencies';
|
||||
|
||||
export async function libraryGenerator(host: Tree, schema: Schema) {
|
||||
@ -36,6 +37,8 @@ export async function libraryGenerator(host: Tree, schema: Schema) {
|
||||
options.style = 'none';
|
||||
}
|
||||
|
||||
extractTsConfigBase(host);
|
||||
|
||||
const initTask = await initGenerator(host, {
|
||||
...options,
|
||||
e2eTestRunner: 'none',
|
||||
|
||||
67
packages/react/src/utils/create-ts-config.ts
Normal file
67
packages/react/src/utils/create-ts-config.ts
Normal file
@ -0,0 +1,67 @@
|
||||
import { Tree } from 'nx/src/generators/tree';
|
||||
import * as shared from '@nrwl/workspace/src/utils/create-ts-config';
|
||||
import { writeJson } from 'nx/src/generators/utils/json';
|
||||
|
||||
export function createTsConfig(
|
||||
host: Tree,
|
||||
projectRoot: string,
|
||||
type: 'app' | 'lib',
|
||||
options: {
|
||||
strict?: boolean;
|
||||
style?: string;
|
||||
bundler?: string;
|
||||
rootProject?: boolean;
|
||||
},
|
||||
relativePathToRootTsConfig: string
|
||||
) {
|
||||
const json = {
|
||||
compilerOptions: {
|
||||
jsx: 'react-jsx',
|
||||
allowJs: false,
|
||||
esModuleInterop: false,
|
||||
allowSyntheticDefaultImports: true,
|
||||
strict: options.strict,
|
||||
},
|
||||
files: [],
|
||||
include: [],
|
||||
references: [
|
||||
{
|
||||
path: type === 'app' ? './tsconfig.app.json' : './tsconfig.lib.json',
|
||||
},
|
||||
],
|
||||
} as any;
|
||||
|
||||
if (options.style === '@emotion/styled') {
|
||||
json.compilerOptions.jsxImportSource = '@emotion/react';
|
||||
}
|
||||
|
||||
if (options.bundler === 'vite') {
|
||||
json.compilerOptions.types = ['vite/client'];
|
||||
}
|
||||
|
||||
// inline tsconfig.base.json into the project
|
||||
if (options.rootProject) {
|
||||
json.compileOnSave = false;
|
||||
json.compilerOptions = {
|
||||
...shared.tsConfigBaseOptions,
|
||||
...json.compilerOptions,
|
||||
};
|
||||
json.exclude = ['node_modules', 'tmp'];
|
||||
} else {
|
||||
json.extends = relativePathToRootTsConfig;
|
||||
}
|
||||
|
||||
writeJson(host, `${projectRoot}/tsconfig.json`, json);
|
||||
}
|
||||
|
||||
export function extractTsConfigBase(host: Tree) {
|
||||
shared.extractTsConfigBase(host);
|
||||
|
||||
if (host.exists('vite.config.ts')) {
|
||||
const vite = host.read('vite.config.ts').toString();
|
||||
host.write(
|
||||
'vite.config.ts',
|
||||
vite.replace(`projects: []`, `projects: ['tsconfig.base.json']`)
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -412,6 +412,9 @@ export function writeViteConfig(tree: Tree, options: Schema) {
|
||||
host: 'localhost',
|
||||
},`;
|
||||
|
||||
const projectsTsConfig = tree.exists('tsconfig.base.json')
|
||||
? "'tsconfig.base.json'"
|
||||
: '';
|
||||
switch (options.uiFramework) {
|
||||
case 'react':
|
||||
viteConfigContent = `
|
||||
@ -432,7 +435,7 @@ ${options.includeVitest ? '/// <reference types="vitest" />' : ''}
|
||||
react(),
|
||||
tsconfigPaths({
|
||||
root: '${offsetFromRoot(projectConfig.root)}',
|
||||
projects: ['tsconfig.base.json'],
|
||||
projects: [${projectsTsConfig}],
|
||||
}),
|
||||
],
|
||||
${buildOption}
|
||||
@ -457,7 +460,7 @@ ${options.includeVitest ? '/// <reference types="vitest" />' : ''}
|
||||
${options.includeLib ? dtsPlugin : ''}
|
||||
tsconfigPaths({
|
||||
root: '${offsetFromRoot(projectConfig.root)}',
|
||||
projects: ['tsconfig.base.json'],
|
||||
projects: [${projectsTsConfig}],
|
||||
}),
|
||||
],
|
||||
${buildOption}
|
||||
|
||||
@ -1,20 +0,0 @@
|
||||
{
|
||||
"compileOnSave": false,
|
||||
"compilerOptions": {
|
||||
"rootDir": ".",
|
||||
"sourceMap": true,
|
||||
"declaration": false,
|
||||
"moduleResolution": "node",
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"importHelpers": true,
|
||||
"target": "es2015",
|
||||
"module": "esnext",
|
||||
"lib": ["es2017", "dom"],
|
||||
"skipLibCheck": true,
|
||||
"skipDefaultLibCheck": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {}
|
||||
},
|
||||
"exclude": ["node_modules", "tmp"]
|
||||
}
|
||||
48
packages/workspace/src/utils/create-ts-config.ts
Normal file
48
packages/workspace/src/utils/create-ts-config.ts
Normal file
@ -0,0 +1,48 @@
|
||||
import { Tree } from 'nx/src/generators/tree';
|
||||
import { readJson, updateJson, writeJson } from 'nx/src/generators/utils/json';
|
||||
|
||||
export const tsConfigBaseOptions = {
|
||||
rootDir: '.',
|
||||
sourceMap: true,
|
||||
declaration: false,
|
||||
moduleResolution: 'node',
|
||||
emitDecoratorMetadata: true,
|
||||
experimentalDecorators: true,
|
||||
importHelpers: true,
|
||||
target: 'es2015',
|
||||
module: 'esnext',
|
||||
lib: ['es2017', 'dom'],
|
||||
skipLibCheck: true,
|
||||
skipDefaultLibCheck: true,
|
||||
baseUrl: '.',
|
||||
};
|
||||
|
||||
export function extractTsConfigBase(host: Tree) {
|
||||
if (host.exists('tsconfig.base.json')) return;
|
||||
|
||||
const tsconfig = readJson(host, 'tsconfig.json');
|
||||
const baseCompilerOptions = {} as any;
|
||||
for (let compilerOption of Object.keys(tsConfigBaseOptions)) {
|
||||
baseCompilerOptions[compilerOption] =
|
||||
tsconfig.compilerOptions[compilerOption];
|
||||
delete tsconfig.compilerOptions[compilerOption];
|
||||
}
|
||||
writeJson(host, 'tsconfig.base.json', {
|
||||
compileOnSave: false,
|
||||
compilerOptions: baseCompilerOptions,
|
||||
exclude: tsconfig.exclude,
|
||||
});
|
||||
tsconfig.extends = './tsconfig.base.json';
|
||||
delete tsconfig.compileOnSave;
|
||||
delete tsconfig.exclude;
|
||||
|
||||
writeJson(host, 'tsconfig.json', tsconfig);
|
||||
|
||||
// special case for updating e2e tests.
|
||||
if (host.exists('e2e/tsconfig.json')) {
|
||||
updateJson(host, 'e2e/tsconfig.json', (json) => {
|
||||
json.extends = '../tsconfig.base.json';
|
||||
return json;
|
||||
});
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user