Skip to content

Commit 61d1dfd

Browse files
committed
fix: Edge cases exist which causes ts-node to fail with register script (fixes #162)
1 parent 5ce0ece commit 61d1dfd

File tree

5 files changed

+47
-30
lines changed

5 files changed

+47
-30
lines changed

src/transformer.ts

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import path from "path";
22
import ts, { CompilerOptions } from "typescript";
3-
import { RunMode, TsTransformPathsConfig, TsTransformPathsContext, VisitorContext } from "./types";
3+
import { RunMode, TsNodeState, TsTransformPathsConfig, TsTransformPathsContext, VisitorContext } from "./types";
44
import { nodeVisitor } from "./visitor";
55
import { createHarmonyFactory } from "./harmony";
66
import { Minimatch } from "minimatch";
@@ -16,6 +16,7 @@ function getTsProperties(args: Parameters<typeof transformer>) {
1616
let fileNames: readonly string[] | undefined;
1717
let compilerOptions: CompilerOptions;
1818
let runMode: RunMode;
19+
let tsNodeState: TsNodeState | undefined;
1920

2021
const { 0: program, 2: extras, 3: manualTransformOptions } = args;
2122

@@ -25,13 +26,11 @@ function getTsProperties(args: Parameters<typeof transformer>) {
2526

2627
/* Determine RunMode & Setup */
2728
// Note: ts-node passes a Program with the paths property stripped, so we do some comparison to determine if it's the caller
28-
const maybeIsTsNode =
29-
tsNodeProps &&
30-
(!program ||
31-
(compilerOptions!.configFilePath === tsNodeProps.compilerOptions.configFilePath && !compilerOptions!.paths));
29+
const isTsNode =
30+
tsNodeProps && (!program || compilerOptions!.configFilePath === tsNodeProps.compilerOptions.configFilePath);
3231

3332
// RunMode: Program
34-
if (program && !maybeIsTsNode) {
33+
if (program && !isTsNode) {
3534
runMode = RunMode.Program;
3635
compilerOptions = compilerOptions!;
3736
}
@@ -42,26 +41,32 @@ function getTsProperties(args: Parameters<typeof transformer>) {
4241
compilerOptions = manualTransformOptions.compilerOptions!;
4342
}
4443
// RunMode: TsNode
45-
else if (maybeIsTsNode) {
44+
else if (isTsNode) {
4645
fileNames = tsNodeProps.fileNames;
47-
48-
runMode =
49-
!program || (fileNames.length > 1 && program.getRootFileNames().length === 1)
50-
? RunMode.TsNodeTranspileOnly
51-
: RunMode.TsNode;
52-
53-
compilerOptions = {
54-
...(program?.getCompilerOptions() ?? {}),
55-
...tsNodeProps!.compilerOptions
56-
};
46+
runMode = RunMode.TsNode;
47+
48+
tsNodeState =
49+
!program ||
50+
(fileNames.length > 1 && program?.getRootFileNames().length === 1) ||
51+
(!compilerOptions!.paths && tsNodeProps!.compilerOptions.paths)
52+
? TsNodeState.Stripped
53+
: TsNodeState.Full;
54+
55+
compilerOptions =
56+
tsNodeState === TsNodeState.Full
57+
? compilerOptions!
58+
: {
59+
...(program?.getCompilerOptions() ?? {}),
60+
...tsNodeProps!.compilerOptions,
61+
};
5762
} else {
5863
throw new Error(
5964
`Cannot transform without a Program, ts-node instance, or manual parameters supplied. ` +
6065
`Make sure you're using ts-patch or ts-node with transpileOnly.`
6166
);
6267
}
6368

64-
return { tsInstance, compilerOptions, fileNames, runMode };
69+
return { tsInstance, compilerOptions, fileNames, runMode, tsNodeState };
6570
}
6671

6772
// endregion
@@ -88,7 +93,8 @@ export default function transformer(
8893
tsInstance,
8994
compilerOptions,
9095
fileNames,
91-
runMode
96+
runMode,
97+
tsNodeState
9298
} = getTsProperties([ program, pluginConfig, transformerExtras, manualTransformOptions ]);
9399

94100
const rootDirs = compilerOptions.rootDirs?.filter(path.isAbsolute);
@@ -97,14 +103,12 @@ export default function transformer(
97103

98104
/* Add supplements for various run modes */
99105
let emitHost = transformationContext.getEmitHost();
100-
if (!emitHost || runMode === RunMode.TsNodeTranspileOnly) {
106+
if (!emitHost || tsNodeState === TsNodeState.Stripped) {
101107
if (!fileNames)
102108
throw new Error(
103109
`No EmitHost found and could not determine files to be processed. Please file an issue with a reproduction!`
104110
);
105111
emitHost = createSyntheticEmitHost(compilerOptions, tsInstance, getCanonicalFileName, fileNames as string[]);
106-
} else if (runMode === RunMode.TsNode) {
107-
Object.assign(emitHost, { getCompilerOptions: () => compilerOptions });
108112
}
109113

110114
/* Create Visitor Context */
@@ -125,6 +129,7 @@ export default function transformer(
125129
tsVersionMinor,
126130
emitHost,
127131
runMode,
132+
tsNodeState,
128133
excludeMatchers: config.exclude?.map((globPattern) => new Minimatch(globPattern, { matchBase: true })),
129134
outputFileNamesCache: new Map(),
130135
// Get paths patterns appropriate for TS compiler version

src/types.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export interface TsTransformPathsContext {
3636
readonly tsVersionMinor: number;
3737
readonly tsFactory?: ts.NodeFactory;
3838
readonly runMode: RunMode;
39+
readonly tsNodeState?: TsNodeState;
3940
readonly program?: ts.Program;
4041
readonly config: TsTransformPathsConfig;
4142
readonly compilerOptions: CompilerOptions;
@@ -64,9 +65,13 @@ export interface VisitorContext extends TsTransformPathsContext {
6465

6566
export enum RunMode {
6667
TsNode = "ts-node",
67-
TsNodeTranspileOnly = "ts-node-transpile-only",
6868
Manual = "manual",
69-
Program = "program"
69+
Program = "program",
70+
}
71+
72+
export enum TsNodeState {
73+
Full,
74+
Stripped,
7075
}
7176

7277
// endregion

src/utils/ts-helpers.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ export function getTsNodeRegistrationProperties(tsInstance: typeof ts) {
100100
const fileNames = pcl?.fileNames || config.fileNames;
101101
const compilerOptions = Object.assign(config.options, options.compilerOptions, { outDir: pcl?.options.outDir });
102102

103-
return { compilerOptions, fileNames };
103+
return { compilerOptions, fileNames, tsNodeOptions: options };
104104
}
105105

106106
// endregion

test/projects/extras/tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22
"include": [ "src" ],
33

44
"ts-node": {
5-
"transpileOnly": true,
65
"require": [ "typescript-transform-paths/register" ]
76
},
87

98
"compilerOptions": {
109
"noEmit": true,
10+
"outDir": "dist",
1111

1212
"rootDir": ".",
1313
"module": "CommonJS",

test/tests/extras.test.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,16 @@ describe(`Extra Tests`, () => {
3333
}
3434
});
3535

36-
test(`Register script transforms with ts-node`, () => {
37-
const res = execSync("npx ts-node src/index.ts", { cwd: projectRoot }).toString();
38-
expect(res).toMatch(/^null($|\r?\n)/);
39-
});
36+
describe(`ts-node register script`, () => {
37+
test(`Works with --transpileOnly`, () => {
38+
const res = execSync("npx ts-node --transpileOnly src/index.ts", { cwd: projectRoot }).toString();
39+
expect(res).toMatch(/^null($|\r?\n)/);
40+
});
41+
42+
test(`Works with --typeCheck`, () => {
43+
const res = execSync("npx ts-node --typeCheck src/index.ts", { cwd: projectRoot }).toString();
44+
expect(res).toMatch(/^null($|\r?\n)/);
45+
});
46+
})
4047
});
4148
});

0 commit comments

Comments
 (0)