Skip to content

Commit b3c6467

Browse files
Jaromir Obrclaude
andcommitted
fix(typescript): no loader required under Bun
Bun transpiles TypeScript natively, so `module.register()` is a no-op stub and a registered tsx/ts-node loader never runs. checkTypeScriptLoader() only string-matched the `require` array against a hardcoded list of Node loaders, so `require: ['tsx/esm']` was mandatory under Bun purely to satisfy that match, forcing tsx into devDependencies to do nothing on every run. Return true early when process.versions.bun is set. This is deliberately Bun-specific rather than "skip the check when the runtime handles TypeScript": Node cannot replace tsx here, as its native type stripping rejects enums and does not resolve extensionless relative imports. Adds unit tests for loaderCheck.js, which had no coverage, pinning both the new Bun branch and the existing Node behaviour. Fixes #5697 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1 parent c780f9a commit b3c6467

2 files changed

Lines changed: 62 additions & 0 deletions

File tree

lib/utils/loaderCheck.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,16 @@
66
* Check if a TypeScript loader is available for test files
77
* Note: This checks if loaders are in the require array, not if packages are installed
88
* Package installation is checked when actually requiring modules
9+
* Always true under Bun, which transpiles TypeScript itself
910
* @param {string[]} requiredModules - Array of required modules from config
1011
* @returns {boolean}
1112
*/
1213
export function checkTypeScriptLoader(requiredModules = []) {
14+
// Bun transpiles TypeScript natively, so no loader is needed.
15+
// Node is not treated the same way: its native type stripping rejects enums
16+
// and does not resolve extensionless relative imports.
17+
if (process.versions.bun) return true
18+
1319
// Check if a loader is configured in the require array
1420
return (
1521
requiredModules.includes('tsx/esm') ||
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { expect } from 'chai'
2+
import { checkTypeScriptLoader, validateTypeScriptSetup } from '../../../lib/utils/loaderCheck.js'
3+
4+
describe('TypeScript loader check', () => {
5+
const hadBun = 'bun' in process.versions
6+
const originalBun = process.versions.bun
7+
8+
afterEach(() => {
9+
if (hadBun) {
10+
process.versions.bun = originalBun
11+
} else {
12+
delete process.versions.bun
13+
}
14+
})
15+
16+
describe('on Node', () => {
17+
beforeEach(() => {
18+
delete process.versions.bun
19+
})
20+
21+
it('detects a configured loader', () => {
22+
for (const loader of ['tsx/esm', 'tsx/cjs', 'tsx', 'ts-node/esm', 'ts-node/register', 'ts-node']) {
23+
expect(checkTypeScriptLoader([loader]), loader).to.be.true
24+
}
25+
})
26+
27+
it('reports an error for TypeScript tests without a loader', () => {
28+
expect(checkTypeScriptLoader([])).to.be.false
29+
30+
const validation = validateTypeScriptSetup(['basic_test.ts'], [])
31+
expect(validation.hasError).to.be.true
32+
expect(validation.message).to.include('TypeScript Test Files Detected')
33+
})
34+
35+
it('passes when there are no TypeScript test files', () => {
36+
expect(validateTypeScriptSetup(['basic_test.js'], []).hasError).to.be.false
37+
})
38+
})
39+
40+
describe('on Bun', () => {
41+
beforeEach(() => {
42+
process.versions.bun = '1.4.2'
43+
})
44+
45+
// Bun transpiles TypeScript itself, so requiring tsx/ts-node is pointless (#5697)
46+
it('needs no loader in the require array', () => {
47+
expect(checkTypeScriptLoader([])).to.be.true
48+
expect(validateTypeScriptSetup(['basic_test.ts'], []).hasError).to.be.false
49+
})
50+
51+
it('still accepts a configured loader', () => {
52+
expect(checkTypeScriptLoader(['tsx/esm'])).to.be.true
53+
expect(validateTypeScriptSetup(['basic_test.ts'], ['tsx/esm']).hasError).to.be.false
54+
})
55+
})
56+
})

0 commit comments

Comments
 (0)