Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(env use): sync global pkg node exec path #7886

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 8 additions & 0 deletions env/plugin-commands-env/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,22 @@
"@pnpm/config": "workspace:*",
"@pnpm/error": "workspace:*",
"@pnpm/fetch": "workspace:*",
"@pnpm/get-context": "workspace:*",
"@pnpm/link-bins": "workspace:*",
"@pnpm/logger": "^5.0.0",
"@pnpm/node.fetcher": "workspace:*",
"@pnpm/node.resolver": "workspace:*",
"@pnpm/package-bins": "workspace:*",
"@pnpm/read-modules-dir": "workspace:*",
"@pnpm/remove-bins": "workspace:*",
"@pnpm/store-path": "workspace:*",
"@zkochan/cmd-shim": "^6.0.0",
"@zkochan/rimraf": "^2.1.3",
"graceful-fs": "^4.2.11",
"ramda": "npm:@pnpm/ramda@0.28.1",
"is-windows": "^1.0.2",
"load-json-file": "^6.2.0",
"normalize-path": "^3.0.0",
"render-help": "^1.0.3",
"semver": "^7.6.0",
"symlink-dir": "^5.2.1",
Expand All @@ -56,6 +62,8 @@
"@types/adm-zip": "^0.5.5",
"@types/graceful-fs": "^4.1.9",
"@types/is-windows": "^1.0.2",
"@types/normalize-path": "^3.0.2",
"@types/ramda": "0.28.20",
"@types/semver": "7.5.3",
"adm-zip": "^0.5.12",
"execa": "npm:safe-execa@0.1.2",
Expand Down
54 changes: 54 additions & 0 deletions env/plugin-commands-env/src/envUse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,17 @@ import { promises as fs } from 'fs'
import util from 'util'
import gfs from 'graceful-fs'
import path from 'path'
import normalizePath from 'normalize-path'
import { PnpmError } from '@pnpm/error'
import { getBinNodePaths, getPackageBins, preferDirectCmds } from '@pnpm/link-bins'
import { readModulesDir } from '@pnpm/read-modules-dir'
import { getExtraNodePaths } from '@pnpm/get-context'
import { logger } from '@pnpm/logger'
import type { Command } from '@pnpm/package-bins'
import cmdShim from '@zkochan/cmd-shim'
import isWindows from 'is-windows'
import symlinkDir from 'symlink-dir'
import unnest from 'ramda/src/unnest'
import { type NvmNodeCommandOptions } from './node'
import { CURRENT_NODE_DIRNAME, getNodeExecPathInBinDir, getNodeExecPathInNodeDir } from './utils'
import { downloadNodeVersion } from './downloadNodeVersion'
Expand Down Expand Up @@ -41,6 +48,53 @@ export async function envUse (opts: NvmNodeCommandOptions, params: string[]) {
}
const npmBinDir = path.join(npmDir, 'bin')
const cmdShimOpts = { createPwshFile: false }

type CommandInfo = Command & {
ownName: boolean
pkgName: string
makePowerShellShim: boolean
nodeExecPath?: string
}
const globalDepDir = path.join(opts.rootProjectManifestDir, 'node_modules')
const allDeps = await readModulesDir(globalDepDir) ?? []
const directDependencies = new Set(Object.keys((opts.rootProjectManifest?.dependencies ?? {})))
const binWarn = (prefix: string, message: string) => {
logger.info({ message, prefix })
}
const allCmds: CommandInfo[] = unnest(
(await Promise.all(
allDeps.map((alias) => ({
depDir: path.resolve(globalDepDir, alias),
isDirectDependency: directDependencies?.has(alias),
nodeExecPath: src,
}))
.map(async ({ depDir, isDirectDependency, nodeExecPath }) => {
const target = normalizePath(depDir)
const cmds = await getPackageBins({ allowExoticManifests: false, warn: binWarn.bind(null, opts.rootProjectManifestDir) }, target, nodeExecPath)
return cmds.map((cmd) => ({ ...cmd, isDirectDependency }))
})
))
.filter((cmds: Command[]) => cmds.length)
)
const cmdsToLink = preferDirectCmds(allCmds)

await Promise.all(cmdsToLink.map(async (cmd) => {
const nodePath: string[] = []
const virtualStoreDir = path.join(opts.rootProjectManifestDir, opts.virtualStoreDir ?? '')
const extraNodePaths = getExtraNodePaths({ extendNodePath: opts.extendNodePath, nodeLinker: opts.nodeLinker ?? 'isolated', hoistPattern: opts.hoistPattern, virtualStoreDir })
for (const modulesPath of await getBinNodePaths(cmd.path)) {
if (extraNodePaths.includes(modulesPath)) break
nodePath.push(modulesPath)
}
nodePath.push(...extraNodePaths)
const externalBinPath = path.join(opts.bin, cmd.name)
await cmdShim(cmd.path, externalBinPath, {
createPwshFile: cmd.makePowerShellShim,
nodePath,
nodeExecPath: cmd.nodeExecPath,
})
}))

await cmdShim(path.join(npmBinDir, 'npm-cli.js'), path.join(opts.bin, 'npm'), cmdShimOpts)
await cmdShim(path.join(npmBinDir, 'npx-cli.js'), path.join(opts.bin, 'npx'), cmdShimOpts)
} catch {
Expand Down
6 changes: 6 additions & 0 deletions env/plugin-commands-env/src/node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ export type NvmNodeCommandOptions = Pick<Config,
| 'storeDir'
| 'useNodeVersion'
| 'pnpmHomeDir'
| 'rootProjectManifest'
| 'rootProjectManifestDir'
| 'extendNodePath'
| 'nodeLinker'
| 'hoistPattern'
| 'virtualStoreDir'
> & Partial<Pick<Config, 'configDir' | 'cliOptions' | 'sslConfigs'>> & {
remote?: boolean
}
Expand Down
12 changes: 12 additions & 0 deletions env/plugin-commands-env/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,24 @@
{
"path": "../../config/config"
},
{
"path": "../../fs/read-modules-dir"
},
{
"path": "../../network/fetch"
},
{
"path": "../../packages/error"
},
{
"path": "../../pkg-manager/get-context"
},
{
"path": "../../pkg-manager/link-bins"
},
{
"path": "../../pkg-manager/package-bins"
},
{
"path": "../../pkg-manager/remove-bins"
},
Expand Down
2 changes: 1 addition & 1 deletion pkg-manager/get-context/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -544,7 +544,7 @@ export async function getContextForSingleImporter (
return ctx
}

function getExtraNodePaths (
export function getExtraNodePaths (
{ extendNodePath = true, hoistPattern, nodeLinker, virtualStoreDir }: {
extendNodePath?: boolean
hoistPattern?: string[]
Expand Down
6 changes: 3 additions & 3 deletions pkg-manager/link-bins/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ export async function linkBinsOfPkgsByAliases (
return _linkBins(cmdsToLink, binsDir, opts)
}

function preferDirectCmds (allCmds: Array<CommandInfo & { isDirectDependency?: boolean }>) {
export function preferDirectCmds (allCmds: Array<CommandInfo & { isDirectDependency?: boolean }>) {
const [directCmds, hoistedCmds] = partition((cmd) => cmd.isDirectDependency === true, allCmds)
const usedDirectCmds = new Set(directCmds.map((directCmd) => directCmd.name))
return [
Expand Down Expand Up @@ -171,7 +171,7 @@ async function isFromModules (filename: string) {
return normalizePath(real).includes('/node_modules/')
}

async function getPackageBins (
export async function getPackageBins (
opts: {
allowExoticManifests: boolean
warn: WarnFunction
Expand Down Expand Up @@ -280,7 +280,7 @@ function getExeExtension (): string {
return cmdExtension ?? '.exe'
}

async function getBinNodePaths (target: string): Promise<string[]> {
export async function getBinNodePaths (target: string): Promise<string[]> {
const targetDir = path.dirname(target)
try {
const targetRealPath = await fs.realpath(targetDir)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"name": "foo"
"name": "foo",
"version": "1.0.0"
}