Skip to content

Commit

Permalink
fix #1662 and add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
cspotcode committed Mar 5, 2022
1 parent 7862f47 commit 4cdf1a5
Show file tree
Hide file tree
Showing 32 changed files with 184 additions and 16 deletions.
17 changes: 10 additions & 7 deletions src/configuration.ts
Expand Up @@ -100,7 +100,10 @@ export function findAndReadConfig(rawOptions: CreateOptions) {
rawOptions.project,
cwd
);
({ compiler } = resolveCompiler(options.compiler, projectLocalResolveDir));
({ compiler } = resolveCompiler(
options.compiler,
optionBasePaths.compiler ?? projectLocalResolveDir
));
}

return {
Expand Down Expand Up @@ -258,6 +261,9 @@ export function readConfig(
if (options.compiler != null) {
optionBasePaths.compiler = basePath;
}
if (options.swc != null) {
optionBasePaths.swc = basePath;
}

assign(tsNodeOptionsFromTsconfig, options);
}
Expand Down Expand Up @@ -329,19 +335,16 @@ export function resolveAndLoadCompiler(
name: string | undefined,
relativeToPath: string
) {
const { compiler, projectLocalResolveHelper } = resolveCompiler(
name,
relativeToPath
);
const { compiler } = resolveCompiler(name, relativeToPath);
const ts = loadCompiler(compiler);
return { compiler, ts, projectLocalResolveHelper };
return { compiler, ts };
}

function resolveCompiler(name: string | undefined, relativeToPath: string) {
const projectLocalResolveHelper =
createProjectLocalResolveHelper(relativeToPath);
const compiler = projectLocalResolveHelper(name || 'typescript', true);
return { projectLocalResolveHelper, compiler };
return { compiler };
}

/** @internal */
Expand Down
19 changes: 12 additions & 7 deletions src/index.ts
Expand Up @@ -387,6 +387,7 @@ export interface OptionBasePaths {
moduleTypes?: string;
transpiler?: string;
compiler?: string;
swc?: string;
}

/**
Expand Down Expand Up @@ -658,11 +659,15 @@ export function createFromPreloadedConfig(
const transpileOnly =
(options.transpileOnly === true || options.swc === true) &&
options.typeCheck !== true;
const transpiler = options.transpiler
? options.transpiler
: options.swc
? require.resolve('./transpilers/swc.js')
: undefined;
let transpiler: RegisterOptions['transpiler'] | undefined = undefined;
let transpilerBasePath: string | undefined = undefined;
if (options.transpiler) {
transpiler = options.transpiler;
transpilerBasePath = optionBasePaths.transpiler;
} else if (options.swc) {
transpiler = require.resolve('./transpilers/swc.js');
transpilerBasePath = optionBasePaths.swc;
}
const transformers = options.transformers || undefined;
const diagnosticFilters: Array<DiagnosticFilter> = [
{
Expand Down Expand Up @@ -729,8 +734,8 @@ export function createFromPreloadedConfig(
typeof transpiler === 'string' ? transpiler : transpiler[0];
const transpilerOptions =
typeof transpiler === 'string' ? {} : transpiler[1] ?? {};
const transpilerConfigLocalResolveHelper = optionBasePaths.transpiler
? createProjectLocalResolveHelper(optionBasePaths.transpiler!)
const transpilerConfigLocalResolveHelper = transpilerBasePath
? createProjectLocalResolveHelper(transpilerBasePath)
: projectLocalResolveHelper;
const transpilerPath = transpilerConfigLocalResolveHelper(
transpilerName,
Expand Down
59 changes: 59 additions & 0 deletions src/test/pluggable-dep-resolution.spec.ts
@@ -0,0 +1,59 @@
import { context } from './testlib';
import { contextTsNodeUnderTest, resetNodeEnvironment } from './helpers';
import * as expect from 'expect';
import { resolve } from 'path';

const test = context(contextTsNodeUnderTest);

test.suite(
'Pluggable dependency (compiler, transpiler, swc backend) is require()d relative to the tsconfig file that declares it',
(test) => {
test.runSerially();

// The use-case we want to support:
//
// User shares their tsconfig across multiple projects as an npm module named "shared-config", similar to @tsconfig/bases
// In their npm module
// They have tsconfig.json with `swc: true` or `compiler: "ts-patch"` or something like that
// The module declares a dependency on a known working version of @swc/core, or ts-patch, or something like that.
// They use this reusable config via `npm install shared-config` and `"extends": "shared-config/tsconfig.json"`
//
// ts-node should resolve ts-patch or @swc/core relative to the extended tsconfig
// to ensure we use the known working versions.

macro('tsconfig-custom-compiler.json', 'root custom compiler');
macro('tsconfig-custom-transpiler.json', 'root custom transpiler');
macro('tsconfig-swc-custom-backend.json', 'root custom swc backend');
macro('tsconfig-swc-core.json', 'root @swc/core');
macro('tsconfig-swc-wasm.json', 'root @swc/wasm');
macro('tsconfig-swc.json', 'root @swc/core');

macro('node_modules/shared-config/tsconfig-custom-compiler.json', 'shared-config custom compiler');
macro('node_modules/shared-config/tsconfig-custom-transpiler.json', 'shared-config custom transpiler');
macro('node_modules/shared-config/tsconfig-swc-custom-backend.json', 'shared-config custom swc backend');
macro('node_modules/shared-config/tsconfig-swc-core.json', 'shared-config @swc/core');
macro('node_modules/shared-config/tsconfig-swc-wasm.json', 'shared-config @swc/wasm');
macro('node_modules/shared-config/tsconfig-swc.json', 'shared-config @swc/core');

macro('tsconfig-extend-custom-compiler.json', 'shared-config custom compiler');
macro('tsconfig-extend-custom-transpiler.json', 'shared-config custom transpiler');
macro('tsconfig-extend-swc-custom-backend.json', 'shared-config custom swc backend');
macro('tsconfig-extend-swc-core.json', 'shared-config @swc/core');
macro('tsconfig-extend-swc-wasm.json', 'shared-config @swc/wasm');
macro('tsconfig-extend-swc.json', 'shared-config @swc/core');

function macro(config: string, expected: string) {
test(`${config} uses ${expected}`, async (t) => {
t.teardown(resetNodeEnvironment);

const output = t.context.tsNodeUnderTest
.create({
project: resolve('tests/pluggable-dep-resolution', config),
})
.compile('', 'index.ts');

expect(output).toContain(`emit from ${expected}\n`);
});
}
}
);
4 changes: 2 additions & 2 deletions src/transpilers/swc.ts
Expand Up @@ -29,10 +29,10 @@ export function create(createOptions: SwcTranspilerOptions): Transpiler {
} else if (swc == null) {
let swcResolved;
try {
swcResolved = projectLocalResolveHelper('@swc/core', true);
swcResolved = transpilerConfigLocalResolveHelper('@swc/core', true);
} catch (e) {
try {
swcResolved = projectLocalResolveHelper('@swc/wasm', true);
swcResolved = transpilerConfigLocalResolveHelper('@swc/wasm', true);
} catch (e) {
throw new Error(
'swc compiler requires either @swc/core or @swc/wasm to be installed as a dependency. See https://typestrong.org/ts-node/docs/transpilers'
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

@@ -0,0 +1 @@
{ "ts-node": { "transpileOnly": true, "compiler": "custom-compiler" } }
@@ -0,0 +1 @@
{ "ts-node": { "transpileOnly": true, "transpiler": "custom-transpiler" } }
@@ -0,0 +1 @@
{ "extends": "shared-config/tsconfig-custom-compiler.json" }
@@ -0,0 +1 @@
{ "extends": "shared-config/tsconfig-custom-transpiler.json" }
@@ -0,0 +1 @@
{ "extends": "shared-config/tsconfig-swc-core.json" }
@@ -0,0 +1 @@
{ "extends": "shared-config/tsconfig-swc-custom-backend.json" }
@@ -0,0 +1 @@
{ "extends": "shared-config/tsconfig-swc-wasm.json" }
1 change: 1 addition & 0 deletions tests/pluggable-dep-resolution/tsconfig-extend-swc.json
@@ -0,0 +1 @@
{ "extends": "shared-config/tsconfig-swc.json" }
6 changes: 6 additions & 0 deletions tests/pluggable-dep-resolution/tsconfig-swc-core.json
@@ -0,0 +1,6 @@
{
"ts-node": {
"transpileOnly": true,
"transpiler": ["ts-node/transpilers/swc", { "swc": "@swc/core" }]
}
}
@@ -0,0 +1,6 @@
{
"ts-node": {
"transpileOnly": true,
"transpiler": ["ts-node/transpilers/swc", { "swc": "custom-swc" }]
}
}
6 changes: 6 additions & 0 deletions tests/pluggable-dep-resolution/tsconfig-swc-wasm.json
@@ -0,0 +1,6 @@
{
"ts-node": {
"transpileOnly": true,
"transpiler": ["ts-node/transpilers/swc", { "swc": "@swc/wasm" }]
}
}
1 change: 1 addition & 0 deletions tests/pluggable-dep-resolution/tsconfig-swc.json
@@ -0,0 +1 @@
{ "ts-node": { "swc": true } }

0 comments on commit 4cdf1a5

Please sign in to comment.