fix(misc): override customConditions when using an incompatible module resolution (#30477)
## Current Behavior In a few different places (Crystal plugins, executors, generators, helpers) where `ts-node` compiler options are overridden and `moduleResolution` is being set to something other than `node16`, `nodenext`, or `bundler`, an error can occur if the `customConditions` compiler option is being used. ## Expected Behavior When overriding the `ts-node` compiler options and changing forcing `moduleResolution` to have a value that's incompatible with `customConditions`, the latter should be unset (set to `null`) to avoid errors. ## Related Issue(s) Fixes #
This commit is contained in:
parent
30781f7fe3
commit
5dbe040374
@ -484,4 +484,164 @@ describe('convert-to-rspack', () => {
|
||||
"
|
||||
`);
|
||||
});
|
||||
|
||||
it('should configure ts-node in the tsconfig.json file', async () => {
|
||||
const tree = createTreeWithEmptyWorkspace();
|
||||
addProjectConfiguration(tree, 'app', {
|
||||
root: 'apps/app',
|
||||
sourceRoot: 'apps/app/src',
|
||||
projectType: 'application',
|
||||
targets: {
|
||||
build: {
|
||||
executor: '@angular-devkit/build-angular:browser',
|
||||
options: {
|
||||
outputPath: 'dist/apps/app',
|
||||
index: 'apps/app/src/index.html',
|
||||
main: 'apps/app/src/main.ts',
|
||||
polyfills: ['tslib'], // zone.js is not in nx repo's node_modules so simulating it with a package that is
|
||||
tsConfig: 'apps/app/tsconfig.app.json',
|
||||
assets: [
|
||||
'apps/app/src/favicon.ico',
|
||||
'apps/app/src/assets',
|
||||
{ input: 'apps/app/public', glob: '**/*' },
|
||||
],
|
||||
styles: ['apps/app/src/styles.scss'],
|
||||
scripts: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
writeJson(tree, 'apps/app/tsconfig.json', {});
|
||||
updateJson(tree, 'package.json', (json) => {
|
||||
json.scripts ??= {};
|
||||
json.scripts.build = 'nx build';
|
||||
return json;
|
||||
});
|
||||
|
||||
await convertToRspack(tree, { project: 'app', skipFormat: true });
|
||||
|
||||
expect(tree.read('apps/app/tsconfig.json', 'utf-8')).toMatchInlineSnapshot(`
|
||||
"{
|
||||
"ts-node": {
|
||||
"compilerOptions": {
|
||||
"module": "CommonJS",
|
||||
"moduleResolution": "Node10"
|
||||
}
|
||||
}
|
||||
}
|
||||
"
|
||||
`);
|
||||
});
|
||||
|
||||
it('should configure ts-node in the tsconfig.json file to unset "customConditions" when it is defined in the root tsconfig.json file', async () => {
|
||||
const tree = createTreeWithEmptyWorkspace();
|
||||
updateJson(tree, 'tsconfig.base.json', (json) => {
|
||||
json.compilerOptions ??= {};
|
||||
json.compilerOptions.customConditions = ['development'];
|
||||
return json;
|
||||
});
|
||||
addProjectConfiguration(tree, 'app', {
|
||||
root: 'apps/app',
|
||||
sourceRoot: 'apps/app/src',
|
||||
projectType: 'application',
|
||||
targets: {
|
||||
build: {
|
||||
executor: '@angular-devkit/build-angular:browser',
|
||||
options: {
|
||||
outputPath: 'dist/apps/app',
|
||||
index: 'apps/app/src/index.html',
|
||||
main: 'apps/app/src/main.ts',
|
||||
polyfills: ['tslib'], // zone.js is not in nx repo's node_modules so simulating it with a package that is
|
||||
tsConfig: 'apps/app/tsconfig.app.json',
|
||||
assets: [
|
||||
'apps/app/src/favicon.ico',
|
||||
'apps/app/src/assets',
|
||||
{ input: 'apps/app/public', glob: '**/*' },
|
||||
],
|
||||
styles: ['apps/app/src/styles.scss'],
|
||||
scripts: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
writeJson(tree, 'apps/app/tsconfig.json', {});
|
||||
updateJson(tree, 'package.json', (json) => {
|
||||
json.scripts ??= {};
|
||||
json.scripts.build = 'nx build';
|
||||
return json;
|
||||
});
|
||||
|
||||
await convertToRspack(tree, { project: 'app', skipFormat: true });
|
||||
|
||||
expect(tree.read('apps/app/tsconfig.json', 'utf-8')).toMatchInlineSnapshot(`
|
||||
"{
|
||||
"ts-node": {
|
||||
"compilerOptions": {
|
||||
"module": "CommonJS",
|
||||
"moduleResolution": "Node10",
|
||||
"customConditions": null
|
||||
}
|
||||
}
|
||||
}
|
||||
"
|
||||
`);
|
||||
});
|
||||
|
||||
it('should configure ts-node in the tsconfig.json file to unset "customConditions" when it is defined in the project tsconfig.json file', async () => {
|
||||
const tree = createTreeWithEmptyWorkspace();
|
||||
addProjectConfiguration(tree, 'app', {
|
||||
root: 'apps/app',
|
||||
sourceRoot: 'apps/app/src',
|
||||
projectType: 'application',
|
||||
targets: {
|
||||
build: {
|
||||
executor: '@angular-devkit/build-angular:browser',
|
||||
options: {
|
||||
outputPath: 'dist/apps/app',
|
||||
index: 'apps/app/src/index.html',
|
||||
main: 'apps/app/src/main.ts',
|
||||
polyfills: ['tslib'], // zone.js is not in nx repo's node_modules so simulating it with a package that is
|
||||
tsConfig: 'apps/app/tsconfig.app.json',
|
||||
assets: [
|
||||
'apps/app/src/favicon.ico',
|
||||
'apps/app/src/assets',
|
||||
{ input: 'apps/app/public', glob: '**/*' },
|
||||
],
|
||||
styles: ['apps/app/src/styles.scss'],
|
||||
scripts: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
writeJson(tree, 'apps/app/tsconfig.json', {
|
||||
compilerOptions: {
|
||||
customConditions: ['development'],
|
||||
},
|
||||
});
|
||||
updateJson(tree, 'package.json', (json) => {
|
||||
json.scripts ??= {};
|
||||
json.scripts.build = 'nx build';
|
||||
return json;
|
||||
});
|
||||
|
||||
await convertToRspack(tree, { project: 'app', skipFormat: true });
|
||||
|
||||
expect(tree.read('apps/app/tsconfig.json', 'utf-8')).toMatchInlineSnapshot(`
|
||||
"{
|
||||
"compilerOptions": {
|
||||
"customConditions": [
|
||||
"development"
|
||||
]
|
||||
},
|
||||
"ts-node": {
|
||||
"compilerOptions": {
|
||||
"module": "CommonJS",
|
||||
"moduleResolution": "Node10",
|
||||
"customConditions": null
|
||||
}
|
||||
}
|
||||
}
|
||||
"
|
||||
`);
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,12 +1,26 @@
|
||||
import { joinPathFragments, readJson, Tree, writeJson } from '@nx/devkit';
|
||||
import { getRootTsConfigFileName } from '@nx/js';
|
||||
|
||||
export function updateTsconfig(tree: Tree, projectRoot: string) {
|
||||
const tsconfigPath = joinPathFragments(projectRoot, 'tsconfig.json');
|
||||
const tsconfig = readJson(tree, tsconfigPath);
|
||||
tsconfig['ts-node'] = {
|
||||
compilerOptions: {
|
||||
module: 'CommonJS',
|
||||
},
|
||||
};
|
||||
|
||||
tsconfig['ts-node'] ??= {};
|
||||
tsconfig['ts-node'].compilerOptions ??= {};
|
||||
tsconfig['ts-node'].compilerOptions.module = 'CommonJS';
|
||||
tsconfig['ts-node'].compilerOptions.moduleResolution = 'Node10';
|
||||
|
||||
if (tsconfig.compilerOptions?.customConditions) {
|
||||
tsconfig['ts-node'].compilerOptions.customConditions = null;
|
||||
} else {
|
||||
const rootTsconfigFile = getRootTsConfigFileName(tree);
|
||||
if (rootTsconfigFile) {
|
||||
const rootTsconfigJson = readJson(tree, rootTsconfigFile);
|
||||
if (rootTsconfigJson.compilerOptions?.customConditions) {
|
||||
tsconfig['ts-node'].compilerOptions.customConditions = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
writeJson(tree, tsconfigPath, tsconfig);
|
||||
}
|
||||
|
||||
@ -23,7 +23,12 @@ export async function jestExecutor(
|
||||
): Promise<{ success: boolean }> {
|
||||
// Jest registers ts-node with module CJS https://github.com/SimenB/jest/blob/v29.6.4/packages/jest-config/src/readConfigFileAndSetRootDir.ts#L117-L119
|
||||
// We want to support of ESM via 'module':'nodenext', we need to override the resolution until Jest supports it.
|
||||
process.env.TS_NODE_COMPILER_OPTIONS ??= '{"moduleResolution":"node10"}';
|
||||
const existingValue = process.env['TS_NODE_COMPILER_OPTIONS'];
|
||||
process.env['TS_NODE_COMPILER_OPTIONS'] = JSON.stringify({
|
||||
...(existingValue ? JSON.parse(existingValue) : {}),
|
||||
moduleResolution: 'Node10',
|
||||
customConditions: null,
|
||||
});
|
||||
|
||||
const config = await parseJestConfig(options, context);
|
||||
|
||||
|
||||
@ -98,7 +98,7 @@ describe.each([true, false])('@nx/jest/plugin', (disableJestRuntime) => {
|
||||
"options": {
|
||||
"cwd": "proj",
|
||||
"env": {
|
||||
"TS_NODE_COMPILER_OPTIONS": "{"moduleResolution":"node10"}",
|
||||
"TS_NODE_COMPILER_OPTIONS": "{"moduleResolution":"node10","customConditions":null}",
|
||||
},
|
||||
},
|
||||
"outputs": [
|
||||
@ -179,7 +179,7 @@ describe.each([true, false])('@nx/jest/plugin', (disableJestRuntime) => {
|
||||
"options": {
|
||||
"cwd": "proj",
|
||||
"env": {
|
||||
"TS_NODE_COMPILER_OPTIONS": "{"moduleResolution":"node10"}",
|
||||
"TS_NODE_COMPILER_OPTIONS": "{"moduleResolution":"node10","customConditions":null}",
|
||||
},
|
||||
},
|
||||
"outputs": [
|
||||
@ -249,7 +249,7 @@ describe.each([true, false])('@nx/jest/plugin', (disableJestRuntime) => {
|
||||
"options": {
|
||||
"cwd": "proj",
|
||||
"env": {
|
||||
"TS_NODE_COMPILER_OPTIONS": "{"moduleResolution":"node10"}",
|
||||
"TS_NODE_COMPILER_OPTIONS": "{"moduleResolution":"node10","customConditions":null}",
|
||||
},
|
||||
},
|
||||
"outputs": [
|
||||
@ -318,7 +318,7 @@ describe.each([true, false])('@nx/jest/plugin', (disableJestRuntime) => {
|
||||
"options": {
|
||||
"cwd": "proj",
|
||||
"env": {
|
||||
"TS_NODE_COMPILER_OPTIONS": "{"moduleResolution":"node10"}",
|
||||
"TS_NODE_COMPILER_OPTIONS": "{"moduleResolution":"node10","customConditions":null}",
|
||||
},
|
||||
},
|
||||
"outputs": [
|
||||
@ -398,7 +398,7 @@ describe.each([true, false])('@nx/jest/plugin', (disableJestRuntime) => {
|
||||
"options": {
|
||||
"cwd": "proj",
|
||||
"env": {
|
||||
"TS_NODE_COMPILER_OPTIONS": "{"moduleResolution":"node10"}",
|
||||
"TS_NODE_COMPILER_OPTIONS": "{"moduleResolution":"node10","customConditions":null}",
|
||||
},
|
||||
},
|
||||
"outputs": [
|
||||
@ -482,7 +482,7 @@ describe.each([true, false])('@nx/jest/plugin', (disableJestRuntime) => {
|
||||
"options": {
|
||||
"cwd": "proj",
|
||||
"env": {
|
||||
"TS_NODE_COMPILER_OPTIONS": "{"moduleResolution":"node10"}",
|
||||
"TS_NODE_COMPILER_OPTIONS": "{"moduleResolution":"node10","customConditions":null}",
|
||||
},
|
||||
},
|
||||
"outputs": [
|
||||
@ -552,7 +552,7 @@ describe.each([true, false])('@nx/jest/plugin', (disableJestRuntime) => {
|
||||
"options": {
|
||||
"cwd": "proj",
|
||||
"env": {
|
||||
"TS_NODE_COMPILER_OPTIONS": "{"moduleResolution":"node10"}",
|
||||
"TS_NODE_COMPILER_OPTIONS": "{"moduleResolution":"node10","customConditions":null}",
|
||||
},
|
||||
},
|
||||
"outputs": [
|
||||
@ -632,7 +632,7 @@ describe.each([true, false])('@nx/jest/plugin', (disableJestRuntime) => {
|
||||
"options": {
|
||||
"cwd": "proj",
|
||||
"env": {
|
||||
"TS_NODE_COMPILER_OPTIONS": "{"moduleResolution":"node10"}",
|
||||
"TS_NODE_COMPILER_OPTIONS": "{"moduleResolution":"node10","customConditions":null}",
|
||||
},
|
||||
},
|
||||
"outputs": [
|
||||
@ -702,7 +702,7 @@ describe.each([true, false])('@nx/jest/plugin', (disableJestRuntime) => {
|
||||
"options": {
|
||||
"cwd": "proj",
|
||||
"env": {
|
||||
"TS_NODE_COMPILER_OPTIONS": "{"moduleResolution":"node10"}",
|
||||
"TS_NODE_COMPILER_OPTIONS": "{"moduleResolution":"node10","customConditions":null}",
|
||||
},
|
||||
},
|
||||
"outputs": [
|
||||
@ -782,7 +782,7 @@ describe.each([true, false])('@nx/jest/plugin', (disableJestRuntime) => {
|
||||
"options": {
|
||||
"cwd": "proj",
|
||||
"env": {
|
||||
"TS_NODE_COMPILER_OPTIONS": "{"moduleResolution":"node10"}",
|
||||
"TS_NODE_COMPILER_OPTIONS": "{"moduleResolution":"node10","customConditions":null}",
|
||||
},
|
||||
},
|
||||
"outputs": [
|
||||
@ -852,7 +852,7 @@ describe.each([true, false])('@nx/jest/plugin', (disableJestRuntime) => {
|
||||
"options": {
|
||||
"cwd": "proj",
|
||||
"env": {
|
||||
"TS_NODE_COMPILER_OPTIONS": "{"moduleResolution":"node10"}",
|
||||
"TS_NODE_COMPILER_OPTIONS": "{"moduleResolution":"node10","customConditions":null}",
|
||||
},
|
||||
},
|
||||
"outputs": [
|
||||
|
||||
@ -253,13 +253,21 @@ async function buildJestTargets(
|
||||
const targets: Record<string, TargetConfiguration> = {};
|
||||
const namedInputs = getNamedInputs(projectRoot, context);
|
||||
|
||||
const existingTsNodeCompilerOptions = process.env['TS_NODE_COMPILER_OPTIONS'];
|
||||
const tsNodeCompilerOptions = JSON.stringify({
|
||||
...(existingTsNodeCompilerOptions
|
||||
? JSON.parse(existingTsNodeCompilerOptions)
|
||||
: {}),
|
||||
moduleResolution: 'node10',
|
||||
customConditions: null,
|
||||
});
|
||||
const target: TargetConfiguration = (targets[options.targetName] = {
|
||||
command: 'jest',
|
||||
options: {
|
||||
cwd: projectRoot,
|
||||
// Jest registers ts-node with module CJS https://github.com/SimenB/jest/blob/v29.6.4/packages/jest-config/src/readConfigFileAndSetRootDir.ts#L117-L119
|
||||
// We want to support of ESM via 'module':'nodenext', we need to override the resolution until Jest supports it.
|
||||
env: { TS_NODE_COMPILER_OPTIONS: '{"moduleResolution":"node10"}' },
|
||||
env: { TS_NODE_COMPILER_OPTIONS: tsNodeCompilerOptions },
|
||||
},
|
||||
metadata: {
|
||||
technologies: ['jest'],
|
||||
@ -341,7 +349,7 @@ async function buildJestTargets(
|
||||
outputs,
|
||||
options: {
|
||||
cwd: projectRoot,
|
||||
env: { TS_NODE_COMPILER_OPTIONS: '{"moduleResolution":"node10"}' },
|
||||
env: { TS_NODE_COMPILER_OPTIONS: tsNodeCompilerOptions },
|
||||
},
|
||||
metadata: {
|
||||
technologies: ['jest'],
|
||||
@ -481,9 +489,7 @@ async function buildJestTargets(
|
||||
outputs,
|
||||
options: {
|
||||
cwd: projectRoot,
|
||||
env: {
|
||||
TS_NODE_COMPILER_OPTIONS: '{"moduleResolution":"node10"}',
|
||||
},
|
||||
env: { TS_NODE_COMPILER_OPTIONS: tsNodeCompilerOptions },
|
||||
},
|
||||
metadata: {
|
||||
technologies: ['jest'],
|
||||
|
||||
@ -60,8 +60,6 @@
|
||||
"semver": "^7.5.3",
|
||||
"source-map-support": "0.5.19",
|
||||
"tinyglobby": "^0.2.12",
|
||||
"ts-node": "10.9.1",
|
||||
"tsconfig-paths": "^4.1.2",
|
||||
"tslib": "^2.3.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
||||
@ -1,21 +0,0 @@
|
||||
export function tsNodeRegister(file: string, tsConfig?: string) {
|
||||
if (!file?.endsWith('.ts')) return;
|
||||
// Register TS compiler lazily
|
||||
require('ts-node').register({
|
||||
project: tsConfig,
|
||||
compilerOptions: {
|
||||
module: 'CommonJS',
|
||||
types: ['node'],
|
||||
},
|
||||
});
|
||||
|
||||
if (!tsConfig) return;
|
||||
|
||||
// Register paths in tsConfig
|
||||
const tsconfigPaths = require('tsconfig-paths');
|
||||
const { absoluteBaseUrl: baseUrl, paths } =
|
||||
tsconfigPaths.loadConfig(tsConfig);
|
||||
if (baseUrl && paths) {
|
||||
tsconfigPaths.register({ baseUrl, paths });
|
||||
}
|
||||
}
|
||||
@ -245,6 +245,7 @@ export function getTranspiler(
|
||||
// use NodeJs module resolution until support for TS 4.x is dropped and then
|
||||
// we can switch to Node10
|
||||
compilerOptions.moduleResolution = ts.ModuleResolutionKind.NodeJs;
|
||||
compilerOptions.customConditions = null;
|
||||
compilerOptions.target = ts.ScriptTarget.ES2021;
|
||||
compilerOptions.inlineSourceMap = true;
|
||||
compilerOptions.skipLibCheck = true;
|
||||
|
||||
@ -88,7 +88,7 @@ describe('@nx/rspack', () => {
|
||||
],
|
||||
"cwd": "my-app",
|
||||
"env": {
|
||||
"TS_NODE_COMPILER_OPTIONS": "{"moduleResolution":"Node10","module":"CommonJS"}",
|
||||
"TS_NODE_COMPILER_OPTIONS": "{"moduleResolution":"Node10","module":"CommonJS","customConditions":null}",
|
||||
},
|
||||
},
|
||||
"outputs": [],
|
||||
@ -106,7 +106,7 @@ describe('@nx/rspack', () => {
|
||||
],
|
||||
"cwd": "my-app",
|
||||
"env": {
|
||||
"TS_NODE_COMPILER_OPTIONS": "{"moduleResolution":"Node10","module":"CommonJS"}",
|
||||
"TS_NODE_COMPILER_OPTIONS": "{"moduleResolution":"Node10","module":"CommonJS","customConditions":null}",
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -118,7 +118,7 @@ describe('@nx/rspack', () => {
|
||||
],
|
||||
"cwd": "my-app",
|
||||
"env": {
|
||||
"TS_NODE_COMPILER_OPTIONS": "{"moduleResolution":"Node10","module":"CommonJS"}",
|
||||
"TS_NODE_COMPILER_OPTIONS": "{"moduleResolution":"Node10","module":"CommonJS","customConditions":null}",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@ -187,6 +187,7 @@ async function createRspackTargets(
|
||||
...(existingValue ? JSON.parse(existingValue) : {}),
|
||||
module: 'CommonJS',
|
||||
moduleResolution: 'Node10',
|
||||
customConditions: null,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -844,6 +844,7 @@ describe('@nx/storybook:configuration for Storybook v7', () => {
|
||||
"ts-node": {
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node10",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { updateJson, type Tree } from '@nx/devkit';
|
||||
import { readJson, updateJson, type Tree } from '@nx/devkit';
|
||||
import { getRootTsConfigFileName } from '@nx/js';
|
||||
|
||||
/**
|
||||
* This is a temporary fix for Storybook to support TypeScript configuration files.
|
||||
@ -12,21 +13,23 @@ export function editRootTsConfig(tree: Tree) {
|
||||
}
|
||||
|
||||
updateJson(tree, 'tsconfig.json', (json) => {
|
||||
if (json['ts-node']) {
|
||||
json['ts-node'] = {
|
||||
...json['ts-node'],
|
||||
compilerOptions: {
|
||||
...(json['ts-node'].compilerOptions ?? {}),
|
||||
module: 'commonjs',
|
||||
},
|
||||
};
|
||||
json['ts-node'] ??= {};
|
||||
json['ts-node'].compilerOptions ??= {};
|
||||
json['ts-node'].compilerOptions.module = 'commonjs';
|
||||
json['ts-node'].compilerOptions.moduleResolution = 'node10';
|
||||
|
||||
if (json.compilerOptions?.customConditions) {
|
||||
json['ts-node'].compilerOptions.customConditions = null;
|
||||
} else {
|
||||
json['ts-node'] = {
|
||||
compilerOptions: {
|
||||
module: 'commonjs',
|
||||
},
|
||||
};
|
||||
const rootTsconfigFile = getRootTsConfigFileName(tree);
|
||||
if (rootTsconfigFile) {
|
||||
const rootTsconfigJson = readJson(tree, rootTsconfigFile);
|
||||
if (rootTsconfigJson.compilerOptions?.customConditions) {
|
||||
json['ts-node'].compilerOptions.customConditions = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return json;
|
||||
});
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user