Skip to content

Commit

Permalink
fix(misc): support ts-node options in tsconfig files (#21723)
Browse files Browse the repository at this point in the history
  • Loading branch information
forivall authored Jun 4, 2024
1 parent 56a3af6 commit 8800a30
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 9 deletions.
90 changes: 86 additions & 4 deletions packages/nx/src/plugins/js/utils/register.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { dirname, join } from 'path';
import type { TsConfigOptions } from 'ts-node';
import type { CompilerOptions } from 'typescript';
import { logger, NX_PREFIX, stripIndent } from '../../../utils/logger';
import { existsSync } from 'fs';
Expand Down Expand Up @@ -80,7 +81,8 @@ export function getSwcTranspiler(
}

export function getTsNodeTranspiler(
compilerOptions: CompilerOptions
compilerOptions: CompilerOptions,
tsNodeOptions?: TsConfigOptions
): (...args: unknown[]) => unknown {
const { register } = require('ts-node') as typeof import('ts-node');
// ts-node doesn't provide a cleanup method
Expand All @@ -103,7 +105,84 @@ export function getTsNodeTranspiler(
};
}

export function getTranspiler(compilerOptions: CompilerOptions) {
/**
* Given the raw "ts-node" sub-object from a tsconfig, return an object with only the properties
* recognized by "ts-node"
*
* Adapted from the function of the same name in ts-node
*/
function filterRecognizedTsConfigTsNodeOptions(jsonObject: any): {
recognized: TsConfigOptions;
unrecognized: any;
} {
if (typeof jsonObject !== 'object' || jsonObject === null) {
return { recognized: {}, unrecognized: {} };
}
const {
compiler,
compilerHost,
compilerOptions,
emit,
files,
ignore,
ignoreDiagnostics,
logError,
preferTsExts,
pretty,
require,
skipIgnore,
transpileOnly,
typeCheck,
transpiler,
scope,
scopeDir,
moduleTypes,
experimentalReplAwait,
swc,
experimentalResolver,
esm,
experimentalSpecifierResolution,
experimentalTsImportSpecifiers,
...unrecognized
} = jsonObject as TsConfigOptions;
const filteredTsConfigOptions = {
compiler,
compilerHost,
compilerOptions,
emit,
experimentalReplAwait,
files,
ignore,
ignoreDiagnostics,
logError,
preferTsExts,
pretty,
require,
skipIgnore,
transpileOnly,
typeCheck,
transpiler,
scope,
scopeDir,
moduleTypes,
swc,
experimentalResolver,
esm,
experimentalSpecifierResolution,
experimentalTsImportSpecifiers,
};
// Use the typechecker to make sure this implementation has the correct set of properties
const catchExtraneousProps: keyof TsConfigOptions =
null as any as keyof typeof filteredTsConfigOptions;
const catchMissingProps: keyof typeof filteredTsConfigOptions =
null as any as keyof TsConfigOptions;
return { recognized: filteredTsConfigOptions, unrecognized };
}

export function getTranspiler(
compilerOptions: CompilerOptions,
tsConfigRaw?: unknown
) {
const preferTsNode = process.env.NX_PREFER_TS_NODE === 'true';

if (!ts) {
Expand All @@ -125,7 +204,9 @@ export function getTranspiler(compilerOptions: CompilerOptions) {

// We can fall back on ts-node if it's available
if (tsNodeInstalled) {
return () => getTsNodeTranspiler(compilerOptions);
const tsNodeOptions =
filterRecognizedTsConfigTsNodeOptions(tsConfigRaw).recognized;
return () => getTsNodeTranspiler(compilerOptions, tsNodeOptions);
}
}

Expand All @@ -138,7 +219,8 @@ export function getTranspiler(compilerOptions: CompilerOptions) {
* @returns cleanup method
*/
export function registerTranspiler(
compilerOptions: CompilerOptions
compilerOptions: CompilerOptions,
tsConfigRaw?: unknown
): () => void {
// Function to register transpiler that returns cleanup function
const transpiler = getTranspiler(compilerOptions);
Expand Down
13 changes: 8 additions & 5 deletions packages/nx/src/project-graph/plugins/loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,14 @@ export function registerPluginTSTranspiler() {
: {};
const cleanupFns = [
registerTsConfigPaths(tsConfigName),
registerTranspiler({
experimentalDecorators: true,
emitDecoratorMetadata: true,
...tsConfig.options,
}),
registerTranspiler(
{
experimentalDecorators: true,
emitDecoratorMetadata: true,
...tsConfig.options,
},
tsConfig.raw
),
];
unregisterPluginTSTranspiler = () => {
cleanupFns.forEach((fn) => fn?.());
Expand Down

0 comments on commit 8800a30

Please sign in to comment.