Skip to content

Commit 90caf5f

Browse files
committed
fix: add realpath to host to properly resolve monorepos
- tested this in a pnpm repo with symlinked deps and it worked there, so I believe this fixes all pnpm issues - it may also fix some Lerna issues if they were due to symlinks, but I didn't check those - not sure about others, e.g. Rush, Yarn workspaces, Yarn PnP - I figured out this was needed by staring at the TS source code and then I found this line: https://github.com/microsoft/TypeScript/blob/67673f324dd5f9398bb53fd16bf75efd155c32e7/src/compiler/moduleNameResolver.ts#L1412 - it expects `host.realpath` to be implemented for TS's `realPath` to work correctly, otherwise it just returns the path with no transformation (i.e. the path to the symlink instead of the realpath) - this is not documented _anywhere_ and we were hitting this when calling `getEmitOutput`, before even using `moduleNameResolver` - so I just tried implementing it... and it worked! - notably, the other Rollup TS plugins don't implement this either??? - not sure how they don't error on this?? - note that I added a `!` as `realpath` doesn't have to be implemented on `ts.sys`... but it is in the default implementation (see comment) - I originally had a ternary with `fs.realpathSync` if it didn't exist but that is literally what the default implementation uses - can add this back in the future if it becomes an issue
1 parent e8240ae commit 90caf5f

File tree

2 files changed

+11
-2
lines changed

2 files changed

+11
-2
lines changed

__tests__/host.spec.ts

+6-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { afterAll, beforeAll, test, expect, jest } from "@jest/globals";
22
import * as ts from "typescript";
33
import * as path from "path";
44
import { normalizePath as normalize } from "@rollup/pluginutils";
5-
import { remove, ensureDir, writeFile } from "fs-extra";
5+
import { remove, ensureDir, writeFile, ensureSymlink } from "fs-extra";
66

77
import { setTypescriptModule } from "../src/tsproxy";
88
import { LanguageServiceHost } from "../src/host";
@@ -18,12 +18,14 @@ const unaryFuncSnap = { text: unaryFunc };
1818
const local = (x: string) => normalize(path.resolve(__dirname, x));
1919
const testDir = local("__temp/host");
2020
const testFile = `${testDir}/file.ts`;
21+
const linkedTestFile = `${testDir}/link.ts`;
2122
const nonExistent = `${testDir}/this-does-not-exist.ts`;
2223

2324
afterAll(() => remove(testDir));
2425
beforeAll(async () => {
2526
await ensureDir(testDir);
2627
await writeFile(testFile, unaryFunc, "utf8");
28+
await ensureSymlink(testFile, linkedTestFile);
2729
});
2830

2931
test("LanguageServiceHost", async () => {
@@ -55,10 +57,12 @@ test("LanguageServiceHost", async () => {
5557
expect(host.directoryExists(nonExistent)).toBeFalsy();
5658
expect(host.fileExists(nonExistent)).toBeFalsy();
5759
expect(host.fileExists(testFile)).toBeTruthy();
58-
expect(host.readDirectory(testDir)).toEqual([testFile]);
60+
expect(host.readDirectory(testDir)).toEqual([testFile, linkedTestFile]);
5961
expect(host.readFile(nonExistent)).toBeFalsy();
6062
expect(host.readFile(testFile)).toEqual(unaryFunc);
6163
expect(host.useCaseSensitiveFileNames()).toBe(process.platform === "linux");
64+
expect(host.realpath(testFile)).toEqual(testFile);
65+
expect(host.realpath(linkedTestFile)).toEqual(testFile);
6266

6367
// test misc functionality
6468
expect(host.getCompilationSettings()).toEqual(testOpts);

src/host.ts

+5
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,11 @@ export class LanguageServiceHost implements tsTypes.LanguageServiceHost
104104
return tsModule.sys.fileExists(path);
105105
}
106106

107+
public realpath(path: string): string
108+
{
109+
return tsModule.sys.realpath!(path); // this exists in the default implementation: https://github.com/microsoft/TypeScript/blob/ab2523bbe0352d4486f67b73473d2143ad64d03d/src/compiler/sys.ts#L1288
110+
}
111+
107112
public getTypeRootsVersion(): number
108113
{
109114
return 0;

0 commit comments

Comments
 (0)