Skip to content

Commit 5dbe040

Browse files
authored
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 #
1 parent 30781f7 commit 5dbe040

File tree

12 files changed

+230
-62
lines changed

12 files changed

+230
-62
lines changed

packages/angular/src/generators/convert-to-rspack/convert-to-rspack.spec.ts

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,4 +484,164 @@ describe('convert-to-rspack', () => {
484484
"
485485
`);
486486
});
487+
488+
it('should configure ts-node in the tsconfig.json file', async () => {
489+
const tree = createTreeWithEmptyWorkspace();
490+
addProjectConfiguration(tree, 'app', {
491+
root: 'apps/app',
492+
sourceRoot: 'apps/app/src',
493+
projectType: 'application',
494+
targets: {
495+
build: {
496+
executor: '@angular-devkit/build-angular:browser',
497+
options: {
498+
outputPath: 'dist/apps/app',
499+
index: 'apps/app/src/index.html',
500+
main: 'apps/app/src/main.ts',
501+
polyfills: ['tslib'], // zone.js is not in nx repo's node_modules so simulating it with a package that is
502+
tsConfig: 'apps/app/tsconfig.app.json',
503+
assets: [
504+
'apps/app/src/favicon.ico',
505+
'apps/app/src/assets',
506+
{ input: 'apps/app/public', glob: '**/*' },
507+
],
508+
styles: ['apps/app/src/styles.scss'],
509+
scripts: [],
510+
},
511+
},
512+
},
513+
});
514+
writeJson(tree, 'apps/app/tsconfig.json', {});
515+
updateJson(tree, 'package.json', (json) => {
516+
json.scripts ??= {};
517+
json.scripts.build = 'nx build';
518+
return json;
519+
});
520+
521+
await convertToRspack(tree, { project: 'app', skipFormat: true });
522+
523+
expect(tree.read('apps/app/tsconfig.json', 'utf-8')).toMatchInlineSnapshot(`
524+
"{
525+
"ts-node": {
526+
"compilerOptions": {
527+
"module": "CommonJS",
528+
"moduleResolution": "Node10"
529+
}
530+
}
531+
}
532+
"
533+
`);
534+
});
535+
536+
it('should configure ts-node in the tsconfig.json file to unset "customConditions" when it is defined in the root tsconfig.json file', async () => {
537+
const tree = createTreeWithEmptyWorkspace();
538+
updateJson(tree, 'tsconfig.base.json', (json) => {
539+
json.compilerOptions ??= {};
540+
json.compilerOptions.customConditions = ['development'];
541+
return json;
542+
});
543+
addProjectConfiguration(tree, 'app', {
544+
root: 'apps/app',
545+
sourceRoot: 'apps/app/src',
546+
projectType: 'application',
547+
targets: {
548+
build: {
549+
executor: '@angular-devkit/build-angular:browser',
550+
options: {
551+
outputPath: 'dist/apps/app',
552+
index: 'apps/app/src/index.html',
553+
main: 'apps/app/src/main.ts',
554+
polyfills: ['tslib'], // zone.js is not in nx repo's node_modules so simulating it with a package that is
555+
tsConfig: 'apps/app/tsconfig.app.json',
556+
assets: [
557+
'apps/app/src/favicon.ico',
558+
'apps/app/src/assets',
559+
{ input: 'apps/app/public', glob: '**/*' },
560+
],
561+
styles: ['apps/app/src/styles.scss'],
562+
scripts: [],
563+
},
564+
},
565+
},
566+
});
567+
writeJson(tree, 'apps/app/tsconfig.json', {});
568+
updateJson(tree, 'package.json', (json) => {
569+
json.scripts ??= {};
570+
json.scripts.build = 'nx build';
571+
return json;
572+
});
573+
574+
await convertToRspack(tree, { project: 'app', skipFormat: true });
575+
576+
expect(tree.read('apps/app/tsconfig.json', 'utf-8')).toMatchInlineSnapshot(`
577+
"{
578+
"ts-node": {
579+
"compilerOptions": {
580+
"module": "CommonJS",
581+
"moduleResolution": "Node10",
582+
"customConditions": null
583+
}
584+
}
585+
}
586+
"
587+
`);
588+
});
589+
590+
it('should configure ts-node in the tsconfig.json file to unset "customConditions" when it is defined in the project tsconfig.json file', async () => {
591+
const tree = createTreeWithEmptyWorkspace();
592+
addProjectConfiguration(tree, 'app', {
593+
root: 'apps/app',
594+
sourceRoot: 'apps/app/src',
595+
projectType: 'application',
596+
targets: {
597+
build: {
598+
executor: '@angular-devkit/build-angular:browser',
599+
options: {
600+
outputPath: 'dist/apps/app',
601+
index: 'apps/app/src/index.html',
602+
main: 'apps/app/src/main.ts',
603+
polyfills: ['tslib'], // zone.js is not in nx repo's node_modules so simulating it with a package that is
604+
tsConfig: 'apps/app/tsconfig.app.json',
605+
assets: [
606+
'apps/app/src/favicon.ico',
607+
'apps/app/src/assets',
608+
{ input: 'apps/app/public', glob: '**/*' },
609+
],
610+
styles: ['apps/app/src/styles.scss'],
611+
scripts: [],
612+
},
613+
},
614+
},
615+
});
616+
writeJson(tree, 'apps/app/tsconfig.json', {
617+
compilerOptions: {
618+
customConditions: ['development'],
619+
},
620+
});
621+
updateJson(tree, 'package.json', (json) => {
622+
json.scripts ??= {};
623+
json.scripts.build = 'nx build';
624+
return json;
625+
});
626+
627+
await convertToRspack(tree, { project: 'app', skipFormat: true });
628+
629+
expect(tree.read('apps/app/tsconfig.json', 'utf-8')).toMatchInlineSnapshot(`
630+
"{
631+
"compilerOptions": {
632+
"customConditions": [
633+
"development"
634+
]
635+
},
636+
"ts-node": {
637+
"compilerOptions": {
638+
"module": "CommonJS",
639+
"moduleResolution": "Node10",
640+
"customConditions": null
641+
}
642+
}
643+
}
644+
"
645+
`);
646+
});
487647
});
Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,26 @@
11
import { joinPathFragments, readJson, Tree, writeJson } from '@nx/devkit';
2+
import { getRootTsConfigFileName } from '@nx/js';
23

34
export function updateTsconfig(tree: Tree, projectRoot: string) {
45
const tsconfigPath = joinPathFragments(projectRoot, 'tsconfig.json');
56
const tsconfig = readJson(tree, tsconfigPath);
6-
tsconfig['ts-node'] = {
7-
compilerOptions: {
8-
module: 'CommonJS',
9-
},
10-
};
7+
8+
tsconfig['ts-node'] ??= {};
9+
tsconfig['ts-node'].compilerOptions ??= {};
10+
tsconfig['ts-node'].compilerOptions.module = 'CommonJS';
11+
tsconfig['ts-node'].compilerOptions.moduleResolution = 'Node10';
12+
13+
if (tsconfig.compilerOptions?.customConditions) {
14+
tsconfig['ts-node'].compilerOptions.customConditions = null;
15+
} else {
16+
const rootTsconfigFile = getRootTsConfigFileName(tree);
17+
if (rootTsconfigFile) {
18+
const rootTsconfigJson = readJson(tree, rootTsconfigFile);
19+
if (rootTsconfigJson.compilerOptions?.customConditions) {
20+
tsconfig['ts-node'].compilerOptions.customConditions = null;
21+
}
22+
}
23+
}
24+
1125
writeJson(tree, tsconfigPath, tsconfig);
1226
}

packages/jest/src/executors/jest/jest.impl.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,12 @@ export async function jestExecutor(
2323
): Promise<{ success: boolean }> {
2424
// Jest registers ts-node with module CJS https://github.com/SimenB/jest/blob/v29.6.4/packages/jest-config/src/readConfigFileAndSetRootDir.ts#L117-L119
2525
// We want to support of ESM via 'module':'nodenext', we need to override the resolution until Jest supports it.
26-
process.env.TS_NODE_COMPILER_OPTIONS ??= '{"moduleResolution":"node10"}';
26+
const existingValue = process.env['TS_NODE_COMPILER_OPTIONS'];
27+
process.env['TS_NODE_COMPILER_OPTIONS'] = JSON.stringify({
28+
...(existingValue ? JSON.parse(existingValue) : {}),
29+
moduleResolution: 'Node10',
30+
customConditions: null,
31+
});
2732

2833
const config = await parseJestConfig(options, context);
2934

packages/jest/src/plugins/plugin.spec.ts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ describe.each([true, false])('@nx/jest/plugin', (disableJestRuntime) => {
9898
"options": {
9999
"cwd": "proj",
100100
"env": {
101-
"TS_NODE_COMPILER_OPTIONS": "{"moduleResolution":"node10"}",
101+
"TS_NODE_COMPILER_OPTIONS": "{"moduleResolution":"node10","customConditions":null}",
102102
},
103103
},
104104
"outputs": [
@@ -179,7 +179,7 @@ describe.each([true, false])('@nx/jest/plugin', (disableJestRuntime) => {
179179
"options": {
180180
"cwd": "proj",
181181
"env": {
182-
"TS_NODE_COMPILER_OPTIONS": "{"moduleResolution":"node10"}",
182+
"TS_NODE_COMPILER_OPTIONS": "{"moduleResolution":"node10","customConditions":null}",
183183
},
184184
},
185185
"outputs": [
@@ -249,7 +249,7 @@ describe.each([true, false])('@nx/jest/plugin', (disableJestRuntime) => {
249249
"options": {
250250
"cwd": "proj",
251251
"env": {
252-
"TS_NODE_COMPILER_OPTIONS": "{"moduleResolution":"node10"}",
252+
"TS_NODE_COMPILER_OPTIONS": "{"moduleResolution":"node10","customConditions":null}",
253253
},
254254
},
255255
"outputs": [
@@ -318,7 +318,7 @@ describe.each([true, false])('@nx/jest/plugin', (disableJestRuntime) => {
318318
"options": {
319319
"cwd": "proj",
320320
"env": {
321-
"TS_NODE_COMPILER_OPTIONS": "{"moduleResolution":"node10"}",
321+
"TS_NODE_COMPILER_OPTIONS": "{"moduleResolution":"node10","customConditions":null}",
322322
},
323323
},
324324
"outputs": [
@@ -398,7 +398,7 @@ describe.each([true, false])('@nx/jest/plugin', (disableJestRuntime) => {
398398
"options": {
399399
"cwd": "proj",
400400
"env": {
401-
"TS_NODE_COMPILER_OPTIONS": "{"moduleResolution":"node10"}",
401+
"TS_NODE_COMPILER_OPTIONS": "{"moduleResolution":"node10","customConditions":null}",
402402
},
403403
},
404404
"outputs": [
@@ -482,7 +482,7 @@ describe.each([true, false])('@nx/jest/plugin', (disableJestRuntime) => {
482482
"options": {
483483
"cwd": "proj",
484484
"env": {
485-
"TS_NODE_COMPILER_OPTIONS": "{"moduleResolution":"node10"}",
485+
"TS_NODE_COMPILER_OPTIONS": "{"moduleResolution":"node10","customConditions":null}",
486486
},
487487
},
488488
"outputs": [
@@ -552,7 +552,7 @@ describe.each([true, false])('@nx/jest/plugin', (disableJestRuntime) => {
552552
"options": {
553553
"cwd": "proj",
554554
"env": {
555-
"TS_NODE_COMPILER_OPTIONS": "{"moduleResolution":"node10"}",
555+
"TS_NODE_COMPILER_OPTIONS": "{"moduleResolution":"node10","customConditions":null}",
556556
},
557557
},
558558
"outputs": [
@@ -632,7 +632,7 @@ describe.each([true, false])('@nx/jest/plugin', (disableJestRuntime) => {
632632
"options": {
633633
"cwd": "proj",
634634
"env": {
635-
"TS_NODE_COMPILER_OPTIONS": "{"moduleResolution":"node10"}",
635+
"TS_NODE_COMPILER_OPTIONS": "{"moduleResolution":"node10","customConditions":null}",
636636
},
637637
},
638638
"outputs": [
@@ -702,7 +702,7 @@ describe.each([true, false])('@nx/jest/plugin', (disableJestRuntime) => {
702702
"options": {
703703
"cwd": "proj",
704704
"env": {
705-
"TS_NODE_COMPILER_OPTIONS": "{"moduleResolution":"node10"}",
705+
"TS_NODE_COMPILER_OPTIONS": "{"moduleResolution":"node10","customConditions":null}",
706706
},
707707
},
708708
"outputs": [
@@ -782,7 +782,7 @@ describe.each([true, false])('@nx/jest/plugin', (disableJestRuntime) => {
782782
"options": {
783783
"cwd": "proj",
784784
"env": {
785-
"TS_NODE_COMPILER_OPTIONS": "{"moduleResolution":"node10"}",
785+
"TS_NODE_COMPILER_OPTIONS": "{"moduleResolution":"node10","customConditions":null}",
786786
},
787787
},
788788
"outputs": [
@@ -852,7 +852,7 @@ describe.each([true, false])('@nx/jest/plugin', (disableJestRuntime) => {
852852
"options": {
853853
"cwd": "proj",
854854
"env": {
855-
"TS_NODE_COMPILER_OPTIONS": "{"moduleResolution":"node10"}",
855+
"TS_NODE_COMPILER_OPTIONS": "{"moduleResolution":"node10","customConditions":null}",
856856
},
857857
},
858858
"outputs": [

packages/jest/src/plugins/plugin.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -253,13 +253,21 @@ async function buildJestTargets(
253253
const targets: Record<string, TargetConfiguration> = {};
254254
const namedInputs = getNamedInputs(projectRoot, context);
255255

256+
const existingTsNodeCompilerOptions = process.env['TS_NODE_COMPILER_OPTIONS'];
257+
const tsNodeCompilerOptions = JSON.stringify({
258+
...(existingTsNodeCompilerOptions
259+
? JSON.parse(existingTsNodeCompilerOptions)
260+
: {}),
261+
moduleResolution: 'node10',
262+
customConditions: null,
263+
});
256264
const target: TargetConfiguration = (targets[options.targetName] = {
257265
command: 'jest',
258266
options: {
259267
cwd: projectRoot,
260268
// Jest registers ts-node with module CJS https://github.com/SimenB/jest/blob/v29.6.4/packages/jest-config/src/readConfigFileAndSetRootDir.ts#L117-L119
261269
// We want to support of ESM via 'module':'nodenext', we need to override the resolution until Jest supports it.
262-
env: { TS_NODE_COMPILER_OPTIONS: '{"moduleResolution":"node10"}' },
270+
env: { TS_NODE_COMPILER_OPTIONS: tsNodeCompilerOptions },
263271
},
264272
metadata: {
265273
technologies: ['jest'],
@@ -341,7 +349,7 @@ async function buildJestTargets(
341349
outputs,
342350
options: {
343351
cwd: projectRoot,
344-
env: { TS_NODE_COMPILER_OPTIONS: '{"moduleResolution":"node10"}' },
352+
env: { TS_NODE_COMPILER_OPTIONS: tsNodeCompilerOptions },
345353
},
346354
metadata: {
347355
technologies: ['jest'],
@@ -481,9 +489,7 @@ async function buildJestTargets(
481489
outputs,
482490
options: {
483491
cwd: projectRoot,
484-
env: {
485-
TS_NODE_COMPILER_OPTIONS: '{"moduleResolution":"node10"}',
486-
},
492+
env: { TS_NODE_COMPILER_OPTIONS: tsNodeCompilerOptions },
487493
},
488494
metadata: {
489495
technologies: ['jest'],

packages/js/package.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,6 @@
6060
"semver": "^7.5.3",
6161
"source-map-support": "0.5.19",
6262
"tinyglobby": "^0.2.12",
63-
"ts-node": "10.9.1",
64-
"tsconfig-paths": "^4.1.2",
6563
"tslib": "^2.3.0"
6664
},
6765
"peerDependencies": {

packages/js/src/utils/typescript/tsnode-register.ts

Lines changed: 0 additions & 21 deletions
This file was deleted.

packages/nx/src/plugins/js/utils/register.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,7 @@ export function getTranspiler(
245245
// use NodeJs module resolution until support for TS 4.x is dropped and then
246246
// we can switch to Node10
247247
compilerOptions.moduleResolution = ts.ModuleResolutionKind.NodeJs;
248+
compilerOptions.customConditions = null;
248249
compilerOptions.target = ts.ScriptTarget.ES2021;
249250
compilerOptions.inlineSourceMap = true;
250251
compilerOptions.skipLibCheck = true;

0 commit comments

Comments
 (0)