Skip to content

Commit 092320b

Browse files
authored
fix: apply correct fs restrictions for pnpm gvs (#22415)
1 parent 2292140 commit 092320b

1 file changed

Lines changed: 24 additions & 1 deletion

File tree

‎packages/vite/src/node/server/index.ts‎

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import path from 'node:path'
2+
import fs from 'node:fs'
23
import { execSync } from 'node:child_process'
34
import type * as net from 'node:net'
45
import { get as httpGet } from 'node:http'
@@ -1228,10 +1229,10 @@ export async function resolveServerOptions(
12281229

12291230
let allowDirs = server.fs.allow
12301231

1232+
const cwd = searchForPackageRoot(root)
12311233
if (process.versions.pnp) {
12321234
// running a command fails if cwd doesn't exist and root may not exist
12331235
// search for package root to find a path that exists
1234-
const cwd = searchForPackageRoot(root)
12351236
try {
12361237
const enableGlobalCache =
12371238
execSync('yarn config get enableGlobalCache', { cwd })
@@ -1251,6 +1252,28 @@ export async function resolveServerOptions(
12511252
}
12521253
}
12531254

1255+
// pnpm's global virtual store (GVS) may place package files outside workspace root.
1256+
// Read node_modules/.modules.yaml which pnpm always writes on install — this works
1257+
// unconditionally regardless of how Vite is launched (node / npx / pnpm run),
1258+
// avoiding the need for subprocess calls or user-agent sniffing.
1259+
const pnpmModulesYaml = path.join(cwd, 'node_modules', '.modules.yaml')
1260+
try {
1261+
const content = fs.readFileSync(pnpmModulesYaml, 'utf-8')
1262+
const parsed = JSON.parse(content)
1263+
const virtualStoreDir = parsed.virtualStoreDir
1264+
if (virtualStoreDir) {
1265+
if (path.isAbsolute(virtualStoreDir)) {
1266+
allowDirs.push(virtualStoreDir)
1267+
} else if (virtualStoreDir.startsWith('..')) {
1268+
allowDirs.push(
1269+
path.resolve(path.join(cwd, 'node_modules'), virtualStoreDir),
1270+
)
1271+
}
1272+
}
1273+
} catch {
1274+
// .modules.yaml not found or unreadable — not a pnpm project, skip
1275+
}
1276+
12541277
allowDirs = allowDirs.map((i) => resolvedAllowDir(root, i))
12551278

12561279
// only push client dir when vite itself is outside-of-root

0 commit comments

Comments
 (0)