Skip to content

Commit 6384d39

Browse files
ntottenff1451
andauthored
Fix: support Yarn PnP SDK prettierPath entry file (#3911) (#3914)
* Fix Yarn PnP SDK module resolution when prettierPath points to a file When `prettier.prettierPath` is set to a file path like `.yarn/sdks/prettier/index.cjs` (common in Yarn PnP SDK setups), the extension incorrectly treated it as a directory and tried to read `index.cjs/package.json`, causing module loading to fail. This fix: - In `ModuleResolverNode.ts`: Check if the path is a file and use the parent directory to find `package.json` - In `PrettierDynamicInstance.ts`: Detect `.js/.cjs/.mjs` file extensions and use the file directly instead of resolving Fixes the error: "Failed to load module... index.cjs/package.json" * Add test for Yarn PnP SDK prettierPath file resolution Add test fixture and test case to verify that the extension correctly handles `prettierPath` pointing to a `.cjs` file, which is common in Yarn PnP SDK setups. Test fixture structure: - `.yarn/sdks/prettier/index.cjs` - SDK wrapper entry point - `.vscode/settings.json` - with prettierPath pointing to the .cjs file * Refactor comment for clarity on modulePath usage --------- Co-authored-by: 이준영 <54898597+ff1451@users.noreply.github.com>
1 parent c17f004 commit 6384d39

11 files changed

Lines changed: 76 additions & 7 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ All notable changes to the "prettier-vscode" extension will be documented in thi
66

77
## [Unreleased]
88

9+
- Fixed module resolution when `prettierPath` points to a file (e.g., `.yarn/sdks/prettier/index.cjs` in Yarn PnP SDK setups)
10+
911
## [12.1.0]
1012

1113
- [BREAKING CHANGE] Bundled Prettier upgraded from v2.8.8 to v3.x

src/ModuleResolverNode.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,19 @@ export class ModuleResolver implements ModuleResolverInterface {
329329
let modulePackageJsonPath = "";
330330

331331
try {
332-
modulePackageJsonPath = path.join(modulePath, "package.json");
332+
// Check if modulePath is a file or directory
333+
// If it's a file (e.g., .yarn/sdks/prettier/index.cjs), look for package.json in parent directory
334+
let packageDir = modulePath;
335+
try {
336+
const stat = await fs.promises.stat(modulePath);
337+
if (stat.isFile()) {
338+
packageDir = path.dirname(modulePath);
339+
}
340+
} catch {
341+
// If stat fails, assume it's a directory path
342+
}
343+
344+
modulePackageJsonPath = path.join(packageDir, "package.json");
333345
const rawPkgJson = await fs.promises.readFile(modulePackageJsonPath, {
334346
encoding: "utf8",
335347
});

src/PrettierDynamicInstance.ts

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,22 @@ export const PrettierDynamicInstance: PrettierInstanceConstructor = class Pretti
2222
constructor(private modulePath: string) {}
2323

2424
public async import(): Promise</* version of imported prettier */ string> {
25-
// Resolve to actual entry file since ESM doesn't support directory imports
26-
// modulePath is like /path/to/node_modules/prettier, resolve "prettier" from there
27-
const entryPath = resolveModuleEntry(
28-
this.modulePath,
29-
path.basename(this.modulePath),
30-
);
25+
// Check if modulePath is a file or directory
26+
// If it's a file (e.g., .yarn/sdks/prettier/index.cjs), use it directly
27+
// If it's a directory (e.g., node_modules/prettier), resolve the entry
28+
let entryPath: string;
29+
const ext = path.extname(this.modulePath).toLowerCase();
30+
if (ext === ".js" || ext === ".cjs" || ext === ".mjs") {
31+
// modulePath is a file, use it
32+
entryPath = this.modulePath;
33+
} else {
34+
// Resolve to actual entry file since ESM doesn't support directory imports
35+
// modulePath is like /path/to/node_modules/prettier, resolve "prettier" from there
36+
entryPath = resolveModuleEntry(
37+
this.modulePath,
38+
path.basename(this.modulePath),
39+
);
40+
}
3141
const moduleUrl = pathToFileURL(entryPath).href;
3242
const imported = await import(moduleUrl);
3343
// Handle both ESM (Prettier v3+) and CJS (Prettier v2) modules
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import * as assert from "assert";
2+
import { format, getText } from "./formatTestUtils.js";
3+
import { ensureExtensionActivated } from "./testUtils.js";
4+
5+
describe("Test Yarn PnP SDK with prettierPath pointing to .cjs file", () => {
6+
before(async () => {
7+
await ensureExtensionActivated();
8+
});
9+
10+
it("it formats with prettierPath pointing to a .cjs file", async () => {
11+
const { actual } = await format("yarn-pnp-sdk", "index.js");
12+
const expected = await getText("yarn-pnp-sdk", "index.result.js");
13+
assert.equal(actual, expected);
14+
});
15+
});

test-fixtures/test.code-workspace

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@
6565
},
6666
{
6767
"path": "monorepo-subfolder"
68+
},
69+
{
70+
"path": "yarn-pnp-sdk"
6871
}
6972
],
7073
"settings": {
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"prettier.prettierPath": ".yarn/sdks/prettier/index.cjs"
3+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/usr/bin/env node
2+
3+
// Simulates Yarn PnP SDK wrapper for Prettier
4+
// This file is the entry point when prettierPath points to a .cjs file
5+
6+
const prettier = require("prettier");
7+
8+
module.exports = prettier;
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"name": "prettier",
3+
"version": "3.4.2",
4+
"main": "./index.cjs"
5+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
const x={a:1,b:2,c:3}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
const x = { a: 1, b: 2, c: 3 };

0 commit comments

Comments
 (0)