fix(plugin-commands-store): support relative storeDir in store commands (#10490)

close #10290

---------

Co-authored-by: Zoltan Kochan <z@kochan.io>
This commit is contained in:
이종혁
2026-02-07 00:31:47 +09:00
committed by GitHub
parent 559f903a90
commit 5f5f1db2b8
4 changed files with 83 additions and 3 deletions

View File

@@ -0,0 +1,6 @@
---
"@pnpm/plugin-commands-store": patch
"pnpm": patch
---
Fix `pnpm store path` and `pnpm store status` using workspace root for path resolution when `storeDir` is relative [#10290](https://github.com/pnpm/pnpm/issues/10290).

View File

@@ -74,7 +74,7 @@ class StoreStatusError extends PnpmError {
}
}
export type StoreCommandOptions = Pick<Config, 'dir' | 'registries' | 'tag' | 'storeDir' | 'force' | 'dlxCacheMaxAge'> & CreateStoreControllerOptions & {
export type StoreCommandOptions = Pick<Config, 'dir' | 'lockfileDir' | 'registries' | 'tag' | 'storeDir' | 'force' | 'dlxCacheMaxAge'> & CreateStoreControllerOptions & {
reporter?: (logObj: LogBase) => void
}
@@ -85,7 +85,7 @@ export async function handler (opts: StoreCommandOptions, params: string[]): Pro
return statusCmd(opts) as Promise<undefined>
case 'path':
return getStorePath({
pkgRoot: opts.dir,
pkgRoot: opts.workspaceDir ?? opts.dir,
storePath: opts.storeDir,
pnpmHomeDir: opts.pnpmHomeDir,
})
@@ -115,8 +115,9 @@ export async function handler (opts: StoreCommandOptions, params: string[]): Pro
async function statusCmd (opts: StoreCommandOptions): Promise<void> {
const modifiedPkgs = await storeStatus(Object.assign(opts, {
lockfileDir: opts.lockfileDir ?? opts.workspaceDir ?? opts.dir,
storeDir: await getStorePath({
pkgRoot: opts.dir,
pkgRoot: opts.workspaceDir ?? opts.dir,
storePath: opts.storeDir,
pnpmHomeDir: opts.pnpmHomeDir,
}),

View File

@@ -30,3 +30,30 @@ test('CLI prints the current store path', async () => {
expect(candidateStorePath).toBe(expectedStorePath)
})
test('CLI prints the current store path when storeDir is relative', async () => {
prepare()
const workspaceDir = process.cwd()
const subpackageDir = path.join(workspaceDir, 'packages', 'foo')
const relativeStoreDir = '../store'
const candidateStorePath = await store.handler({
cacheDir: path.resolve('cache'),
dir: subpackageDir,
workspaceDir,
pnpmHomeDir: '',
rawConfig: {
registry: REGISTRY,
},
registries: { default: REGISTRY },
storeDir: relativeStoreDir,
userConfig: {},
dlxCacheMaxAge: 0,
virtualStoreDirMaxLength: process.platform === 'win32' ? 60 : 120,
}, ['path'])
// relativeStoreDir should resolve from workspaceDir, not dir
const expectedStorePath = path.join(workspaceDir, relativeStoreDir, STORE_VERSION)
expect(candidateStorePath).toBe(expectedStorePath)
})

View File

@@ -99,3 +99,49 @@ test('CLI does not fail when store status does not find modified packages', asyn
virtualStoreDirMaxLength: process.platform === 'win32' ? 60 : 120,
}, ['status'])
})
test('CLI does not fail when storeDir is relative', async () => {
const project = prepare()
const cacheDir = path.resolve('cache')
const workspaceDir = process.cwd()
const subpackageDir = path.join(workspaceDir, 'packages', 'foo')
const relativeStoreDir = '../.store'
fs.writeFileSync('pnpm-workspace.yaml', `packages:
- "packages/*"
storeDir: "${relativeStoreDir}"
`, 'utf8')
// make subpackage
fs.mkdirSync(subpackageDir, { recursive: true })
fs.writeFileSync(
path.join(subpackageDir, 'package.json'),
JSON.stringify({ name: 'foo', version: '0.0.0' })
)
await execa('node', [
pnpmBin,
'add',
'is-positive@3.1.0',
`--registry=${REGISTRY}`,
'--verify-store-integrity',
])
const modulesState = project.readModulesManifest()
// relativeStoreDir should resolve from workspaceDir, not dir
await store.handler({
cacheDir,
dir: subpackageDir,
workspaceDir,
pnpmHomeDir: '',
rawConfig: {
registry: REGISTRY,
},
registries: modulesState!.registries!,
storeDir: relativeStoreDir,
userConfig: {},
dlxCacheMaxAge: 0,
virtualStoreDirMaxLength: process.platform === 'win32' ? 60 : 120,
}, ['status'])
})