mirror of
https://github.com/pnpm/pnpm.git
synced 2026-07-26 07:27:20 -04:00
fix(headless): .bin directory should be created in hoisted node_modules (#4191)
ref #4073
This commit is contained in:
5
.changeset/four-cycles-lick.md
Normal file
5
.changeset/four-cycles-lick.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@pnpm/headless": patch
|
||||
---
|
||||
|
||||
The commands should be linked to `node_modules/.bin` directory when `nodeLinker=hoisted` is used.
|
||||
@@ -86,7 +86,7 @@ test('preserve subdeps on update', async () => {
|
||||
expect(loadJsonFile<{ version: string }>('node_modules/foobarqar/node_modules/bar/package.json').version).toBe('100.0.0')
|
||||
})
|
||||
|
||||
test('adding a new dependency to one of the the workspace projects', async () => {
|
||||
test('adding a new dependency to one of the workspace projects', async () => {
|
||||
prepareEmpty()
|
||||
|
||||
let [{ manifest }] = await mutateModules([
|
||||
@@ -143,3 +143,20 @@ test('installing the same package with alias and no alias', async () => {
|
||||
expect(loadJsonFile<{ version: string }>('node_modules/dep-of-pkg-with-1-dep/package.json').version).toBe('100.0.0')
|
||||
expect(loadJsonFile<{ version: string }>('node_modules/dep/package.json').version).toBe('100.0.0')
|
||||
})
|
||||
|
||||
test('run pre/postinstall scripts. bin files should be linked in a hoisted node_modules', async () => {
|
||||
const project = prepareEmpty()
|
||||
await addDependenciesToPackage({},
|
||||
['pre-and-postinstall-scripts-example'],
|
||||
await testDefaults({ fastUnpack: false, nodeLinker: 'hoisted', targetDependenciesField: 'devDependencies' })
|
||||
)
|
||||
|
||||
expect(fs.existsSync('node_modules/pre-and-postinstall-scripts-example/generated-by-prepare.js')).toBeFalsy()
|
||||
expect(fs.existsSync('node_modules/pre-and-postinstall-scripts-example/generated-by-preinstall.js')).toBeTruthy()
|
||||
|
||||
const generatedByPreinstall = project.requireModule('pre-and-postinstall-scripts-example/generated-by-preinstall')
|
||||
expect(typeof generatedByPreinstall).toBe('function')
|
||||
|
||||
const generatedByPostinstall = project.requireModule('pre-and-postinstall-scripts-example/generated-by-postinstall')
|
||||
expect(typeof generatedByPostinstall).toBe('function')
|
||||
})
|
||||
|
||||
@@ -284,6 +284,7 @@ export default async (opts: HeadlessOptions) => {
|
||||
let newHoistedDependencies!: HoistedDependencies
|
||||
if (opts.nodeLinker === 'hoisted' && hierarchy && prevGraph) {
|
||||
await linkHoistedModules(opts.storeController, graph, prevGraph, hierarchy, {
|
||||
extendNodePath: opts.extendNodePath,
|
||||
force: opts.force,
|
||||
lockfileDir: opts.lockfileDir,
|
||||
targetEngine: opts.sideEffectsCacheRead && ENGINE_NAME || undefined,
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
import path from 'path'
|
||||
import {
|
||||
progressLogger,
|
||||
removalLogger,
|
||||
statsLogger,
|
||||
} from '@pnpm/core-loggers'
|
||||
import linkBins from '@pnpm/link-bins'
|
||||
import logger from '@pnpm/logger'
|
||||
import {
|
||||
PackageFilesResponse,
|
||||
StoreController,
|
||||
@@ -20,6 +23,7 @@ export default async function linkHoistedModules (
|
||||
prevGraph: DependenciesGraph,
|
||||
hierarchy: DepHierarchy,
|
||||
opts: {
|
||||
extendNodePath?: boolean
|
||||
force: boolean
|
||||
lockfileDir: string
|
||||
targetEngine?: string
|
||||
@@ -36,7 +40,19 @@ export default async function linkHoistedModules (
|
||||
})
|
||||
await Promise.all([
|
||||
...dirsToRemove.map((dir) => tryRemoveDir(dir)),
|
||||
linkAllPkgsInOrder(storeController, graph, prevGraph, hierarchy, opts),
|
||||
...Object.entries(hierarchy)
|
||||
.map(([parentDir, depsHierarchy]) => {
|
||||
function warn (message: string) {
|
||||
logger.info({
|
||||
message,
|
||||
prefix: parentDir,
|
||||
})
|
||||
}
|
||||
return linkAllPkgsInOrder(storeController, graph, prevGraph, depsHierarchy, parentDir, {
|
||||
...opts,
|
||||
warn,
|
||||
})
|
||||
}),
|
||||
])
|
||||
}
|
||||
|
||||
@@ -60,10 +76,13 @@ async function linkAllPkgsInOrder (
|
||||
graph: DependenciesGraph,
|
||||
prevGraph: DependenciesGraph,
|
||||
hierarchy: DepHierarchy,
|
||||
parentDir: string,
|
||||
opts: {
|
||||
extendNodePath?: boolean
|
||||
force: boolean
|
||||
lockfileDir: string
|
||||
targetEngine?: string
|
||||
warn: (message: string) => void
|
||||
}
|
||||
) {
|
||||
await Promise.all(
|
||||
@@ -91,7 +110,14 @@ async function linkAllPkgsInOrder (
|
||||
})
|
||||
}
|
||||
depNode.isBuilt = isBuilt
|
||||
return linkAllPkgsInOrder(storeController, graph, prevGraph, deps, opts)
|
||||
return linkAllPkgsInOrder(storeController, graph, prevGraph, deps, dir, opts)
|
||||
})
|
||||
)
|
||||
const modulesDir = path.join(parentDir, 'node_modules')
|
||||
const binsDir = path.join(modulesDir, '.bin')
|
||||
await linkBins(modulesDir, binsDir, {
|
||||
allowExoticManifests: true,
|
||||
extendNodePath: opts.extendNodePath,
|
||||
warn: opts.warn,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -66,21 +66,21 @@ async function _lockfileToHoistedDepGraph (
|
||||
const tree = hoist(lockfile)
|
||||
const graph: DependenciesGraph = {}
|
||||
const modulesDir = path.join(opts.lockfileDir, 'node_modules')
|
||||
let hierarchy = await fetchDeps(lockfile, opts, graph, modulesDir, tree.dependencies)
|
||||
const hierarchy = {
|
||||
[opts.lockfileDir]: await fetchDeps(lockfile, opts, graph, modulesDir, tree.dependencies),
|
||||
}
|
||||
const directDependenciesByImporterId: DirectDependenciesByImporterId = {
|
||||
'.': directDepsMap(Object.keys(hierarchy), graph),
|
||||
'.': directDepsMap(Object.keys(hierarchy[opts.lockfileDir]), graph),
|
||||
}
|
||||
const symlinkedDirectDependenciesByImporterId: DirectDependenciesByImporterId = { '.': {} }
|
||||
for (const rootDep of Array.from(tree.dependencies)) {
|
||||
const reference = Array.from(rootDep.references)[0]
|
||||
if (reference.startsWith('workspace:')) {
|
||||
const importerId = reference.replace('workspace:', '')
|
||||
const modulesDir = path.join(opts.lockfileDir, importerId, 'node_modules')
|
||||
const projectDir = path.join(opts.lockfileDir, importerId)
|
||||
const modulesDir = path.join(projectDir, 'node_modules')
|
||||
const nextHierarchy = (await fetchDeps(lockfile, opts, graph, modulesDir, rootDep.dependencies))
|
||||
hierarchy = {
|
||||
...hierarchy,
|
||||
...nextHierarchy,
|
||||
}
|
||||
hierarchy[projectDir] = nextHierarchy
|
||||
|
||||
const importer = lockfile.importers[importerId]
|
||||
const importerDir = path.join(opts.lockfileDir, importerId)
|
||||
|
||||
Reference in New Issue
Block a user