Skip to content

Commit 87ed753

Browse files
committed
fix(build): continue after compiler load failures
1 parent bc095a4 commit 87ed753

2 files changed

Lines changed: 41 additions & 10 deletions

File tree

packages/build/src/extensions/internal/loadTypescript.test.ts

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,17 @@ function createProject(packages: Record<string, string>) {
2727
return projectDir;
2828
}
2929

30+
function createBrokenCompiler(projectDir: string, packageName = "typescript") {
31+
const packageDir = join(projectDir, "node_modules", packageName);
32+
33+
mkdirSync(packageDir, { recursive: true });
34+
writeFileSync(
35+
join(packageDir, "package.json"),
36+
JSON.stringify({ name: packageName, main: "index.cjs" })
37+
);
38+
writeFileSync(join(packageDir, "index.cjs"), 'throw new Error("broken compiler");');
39+
}
40+
3041
describe("loadTypescript", () => {
3142
afterEach(() => {
3243
for (const projectDir of projectDirs) {
@@ -64,20 +75,25 @@ describe("loadTypescript", () => {
6475

6576
it("surfaces errors from an installed compiler package", () => {
6677
const projectDir = createProject({});
67-
const packageDir = join(projectDir, "node_modules", "typescript");
68-
69-
mkdirSync(packageDir);
70-
writeFileSync(
71-
join(packageDir, "package.json"),
72-
JSON.stringify({ name: "typescript", main: "index.cjs" })
73-
);
74-
writeFileSync(join(packageDir, "index.cjs"), 'throw new Error("broken compiler");');
78+
createBrokenCompiler(projectDir);
7579

76-
expect(() => loadTypescript(projectDir)).toThrowError(
80+
expect(() => loadTypescript(projectDir, ["typescript"])).toThrowError(
7781
`Failed to load "typescript" from ${projectDir}.`
7882
);
7983
});
8084

85+
it("falls back when an earlier compiler package fails to load", () => {
86+
const projectDir = createProject({
87+
"@typescript/typescript6": "@typescript/typescript6",
88+
});
89+
createBrokenCompiler(projectDir);
90+
91+
const compiler = loadTypescript(projectDir);
92+
93+
expect(compiler.version).toBe("6.0.3");
94+
expect(typeof compiler.transpileModule).toBe("function");
95+
});
96+
8197
it("falls back to the TypeScript 6 compatibility package for TypeScript 7", () => {
8298
const compiler = loadTypescript(
8399
createProject({

packages/build/src/extensions/internal/loadTypescript.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export function loadTypescript(
2727
packageNames: readonly string[] = compilerPackages
2828
): TypeScriptCompiler {
2929
const requireFromProject = createRequire(join(projectDir, "package.json"));
30+
const loadErrors: Error[] = [];
3031

3132
for (const packageName of packageNames) {
3233
let resolvedPackage: string;
@@ -46,14 +47,28 @@ export function loadTypescript(
4647
try {
4748
compiler = requireFromProject(resolvedPackage);
4849
} catch (error) {
49-
throw new Error(`Failed to load "${packageName}" from ${projectDir}.`, { cause: error });
50+
loadErrors.push(
51+
new Error(`Failed to load "${packageName}" from ${projectDir}.`, { cause: error })
52+
);
53+
continue;
5054
}
5155

5256
if (hasTranspileModule(compiler)) {
5357
return compiler;
5458
}
5559
}
5660

61+
if (loadErrors.length === 1) {
62+
throw loadErrors[0];
63+
}
64+
65+
if (loadErrors.length > 1) {
66+
throw new AggregateError(
67+
loadErrors,
68+
`Failed to load a compatible TypeScript compiler from ${projectDir}.`
69+
);
70+
}
71+
5772
throw new Error(
5873
[
5974
"The emitDecoratorMetadata() build extension requires the TypeScript JavaScript compiler API,",

0 commit comments

Comments
 (0)