mirror of
https://github.com/pnpm/pnpm.git
synced 2026-04-11 10:40:53 -04:00
fix: download Node.js from nodejs.org (#3475)
This commit is contained in:
5
.changeset/early-cooks-wash.md
Normal file
5
.changeset/early-cooks-wash.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@pnpm/plugin-commands-nvm": patch
|
||||
---
|
||||
|
||||
Download Node.js from nodejs.org, not from the npm registry.
|
||||
5
.changeset/grumpy-glasses-repair.md
Normal file
5
.changeset/grumpy-glasses-repair.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@pnpm/tarball-fetcher": minor
|
||||
---
|
||||
|
||||
Export waitForFilesIndex().
|
||||
@@ -30,15 +30,23 @@
|
||||
"homepage": "https://github.com/pnpm/pnpm/blob/master/packages/plugin-commands-nvm#readme",
|
||||
"dependencies": {
|
||||
"@pnpm/cli-utils": "workspace:0.6.5",
|
||||
"@pnpm/config": "workspace:12.3.0",
|
||||
"@pnpm/fetch": "workspace:3.1.0",
|
||||
"@pnpm/package-store": "workspace:12.0.7",
|
||||
"@pnpm/store-path": "^5.0.0",
|
||||
"@pnpm/tarball-fetcher": "workspace:9.2.2",
|
||||
"adm-zip": "^0.5.5",
|
||||
"execa": "^5.0.0",
|
||||
"load-json-file": "^6.2.0",
|
||||
"path-name": "^1.0.0",
|
||||
"rename-overwrite": "^4.0.0",
|
||||
"render-help": "^1.0.1",
|
||||
"tempy": "^1.0.0",
|
||||
"write-json-file": "^4.3.0"
|
||||
},
|
||||
"funding": "https://opencollective.com/pnpm",
|
||||
"devDependencies": {
|
||||
"@pnpm/prepare": "workspace:0.0.23"
|
||||
"@pnpm/prepare": "workspace:0.0.23",
|
||||
"@types/adm-zip": "^0.4.34"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,17 @@
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import { docsUrl } from '@pnpm/cli-utils'
|
||||
import fetch from '@pnpm/fetch'
|
||||
import { Config } from '@pnpm/config'
|
||||
import fetch, { createFetchFromRegistry, FetchFromRegistry } from '@pnpm/fetch'
|
||||
import { createCafsStore } from '@pnpm/package-store'
|
||||
import storePath from '@pnpm/store-path'
|
||||
import createFetcher, { waitForFilesIndex } from '@pnpm/tarball-fetcher'
|
||||
import AdmZip from 'adm-zip'
|
||||
import execa from 'execa'
|
||||
import PATH from 'path-name'
|
||||
import renameOverwrite from 'rename-overwrite'
|
||||
import renderHelp from 'render-help'
|
||||
import tempy from 'tempy'
|
||||
import loadJsonFile from 'load-json-file'
|
||||
import writeJsonFile from 'write-json-file'
|
||||
|
||||
@@ -25,19 +32,39 @@ export function help () {
|
||||
})
|
||||
}
|
||||
|
||||
export type NvmNodeCommandOptions = Pick<Config,
|
||||
| 'rawConfig'
|
||||
| 'fetchRetries'
|
||||
| 'fetchRetryFactor'
|
||||
| 'fetchRetryMaxtimeout'
|
||||
| 'fetchRetryMintimeout'
|
||||
| 'fetchRetryMintimeout'
|
||||
| 'fetchTimeout'
|
||||
| 'userAgent'
|
||||
| 'ca'
|
||||
| 'cert'
|
||||
| 'httpProxy'
|
||||
| 'httpsProxy'
|
||||
| 'key'
|
||||
| 'localAddress'
|
||||
| 'noProxy'
|
||||
| 'strictSsl'
|
||||
| 'storeDir'
|
||||
| 'useNodeVersion'
|
||||
| 'pnpmHomeDir'
|
||||
>
|
||||
|
||||
export async function handler (
|
||||
opts: {
|
||||
opts: NvmNodeCommandOptions & {
|
||||
argv: {
|
||||
original: string[]
|
||||
}
|
||||
useNodeVersion?: string
|
||||
pnpmHomeDir: string
|
||||
}
|
||||
) {
|
||||
const nodeDir = await getNodeDir(opts.pnpmHomeDir, opts.useNodeVersion)
|
||||
const nodeDir = await getNodeDir(opts)
|
||||
const { exitCode } = await execa('node', opts.argv.original.slice(1), {
|
||||
env: {
|
||||
[PATH]: `${path.join(nodeDir, 'node_modules/.bin')}${path.delimiter}${process.env[PATH]!}`,
|
||||
[PATH]: `${nodeDir}${path.delimiter}${process.env[PATH]!}`,
|
||||
},
|
||||
stdout: 'inherit',
|
||||
stdin: 'inherit',
|
||||
@@ -45,9 +72,9 @@ export async function handler (
|
||||
return { exitCode }
|
||||
}
|
||||
|
||||
export async function getNodeDir (pnpmHomeDir: string, nodeVersion?: string) {
|
||||
const nodesDir = path.join(pnpmHomeDir, 'nodes')
|
||||
let wantedNodeVersion = nodeVersion ?? (await readNodeVersionsManifest(nodesDir))?.default
|
||||
export async function getNodeDir (opts: NvmNodeCommandOptions) {
|
||||
const nodesDir = path.join(opts.pnpmHomeDir, 'nodes')
|
||||
let wantedNodeVersion = opts.useNodeVersion ?? (await readNodeVersionsManifest(nodesDir))?.default
|
||||
await fs.promises.mkdir(nodesDir, { recursive: true })
|
||||
fs.writeFileSync(path.join(nodesDir, 'pnpm-workspace.yaml'), '', 'utf8')
|
||||
if (wantedNodeVersion == null) {
|
||||
@@ -62,27 +89,72 @@ export async function getNodeDir (pnpmHomeDir: string, nodeVersion?: string) {
|
||||
}
|
||||
const versionDir = path.join(nodesDir, wantedNodeVersion)
|
||||
if (!fs.existsSync(versionDir)) {
|
||||
await installNode(wantedNodeVersion, versionDir)
|
||||
await installNode(wantedNodeVersion, versionDir, opts)
|
||||
}
|
||||
return versionDir
|
||||
return process.platform === 'win32' ? versionDir : path.join(versionDir, 'bin')
|
||||
}
|
||||
|
||||
async function installNode (wantedNodeVersion: string, versionDir: string) {
|
||||
async function installNode (wantedNodeVersion: string, versionDir: string, opts: NvmNodeCommandOptions) {
|
||||
await fs.promises.mkdir(versionDir, { recursive: true })
|
||||
await writeJsonFile(path.join(versionDir, 'package.json'), {})
|
||||
const { exitCode } = await execa('pnpm', ['add', '--use-stderr', `${getNodePkgName()}@${wantedNodeVersion}`], {
|
||||
cwd: versionDir,
|
||||
stdout: 'inherit',
|
||||
})
|
||||
if (exitCode !== 0) {
|
||||
throw new Error(`Couldn't install Node.js ${wantedNodeVersion}`)
|
||||
const { tarball, pkgName } = getNodeJSTarball(wantedNodeVersion)
|
||||
const fetchFromRegistry = createFetchFromRegistry(opts)
|
||||
if (tarball.endsWith('.zip')) {
|
||||
await downloadAndUnpackZip(fetchFromRegistry, tarball, versionDir, pkgName)
|
||||
return
|
||||
}
|
||||
const getCredentials = () => ({ authHeaderValue: undefined, alwaysAuth: undefined })
|
||||
const fetch = createFetcher(fetchFromRegistry, getCredentials, {
|
||||
retry: {
|
||||
maxTimeout: opts.fetchRetryMaxtimeout,
|
||||
minTimeout: opts.fetchRetryMintimeout,
|
||||
retries: opts.fetchRetries,
|
||||
factor: opts.fetchRetryFactor,
|
||||
},
|
||||
timeout: opts.fetchTimeout,
|
||||
})
|
||||
const storeDir = await storePath(process.cwd(), opts.storeDir)
|
||||
const cafsDir = path.join(storeDir, 'files')
|
||||
const cafs = createCafsStore(cafsDir)
|
||||
const { filesIndex } = await fetch.tarball(cafs, { tarball }, {
|
||||
lockfileDir: process.cwd(),
|
||||
})
|
||||
await cafs.importPackage(versionDir, {
|
||||
filesResponse: {
|
||||
filesIndex: await waitForFilesIndex(filesIndex),
|
||||
fromStore: false,
|
||||
},
|
||||
force: true,
|
||||
})
|
||||
}
|
||||
|
||||
function getNodePkgName () {
|
||||
async function downloadAndUnpackZip (
|
||||
fetchFromRegistry: FetchFromRegistry,
|
||||
zipUrl: string,
|
||||
targetDir: string,
|
||||
pkgName: string
|
||||
) {
|
||||
const response = await fetchFromRegistry(zipUrl)
|
||||
const tmp = path.join(tempy.directory(), 'pnpm.zip')
|
||||
const dest = fs.createWriteStream(tmp)
|
||||
await new Promise((resolve, reject) => {
|
||||
response.body.pipe(dest).on('error', reject).on('close', resolve)
|
||||
})
|
||||
const zip = new AdmZip(tmp)
|
||||
const nodeDir = path.dirname(targetDir)
|
||||
zip.extractAllTo(nodeDir, true)
|
||||
await renameOverwrite(path.join(nodeDir, pkgName), targetDir)
|
||||
await fs.promises.unlink(tmp)
|
||||
}
|
||||
|
||||
function getNodeJSTarball (nodeVersion: string) {
|
||||
const platform = process.platform === 'win32' ? 'win' : process.platform
|
||||
const arch = platform === 'win' && process.arch === 'ia32' ? 'x86' : process.arch
|
||||
return `node-${platform}-${arch}`
|
||||
const extension = platform === 'win' ? 'zip' : 'tar.gz'
|
||||
const pkgName = `node-v${nodeVersion}-${platform}-${arch}`
|
||||
return {
|
||||
pkgName,
|
||||
tarball: `https://nodejs.org/download/release/v${nodeVersion}/${pkgName}.${extension}`,
|
||||
}
|
||||
}
|
||||
|
||||
async function readNodeVersionsManifest (nodesDir: string): Promise<{ default?: string }> {
|
||||
|
||||
@@ -10,6 +10,7 @@ test('run specific version of Node.js', async () => {
|
||||
},
|
||||
useNodeVersion: '14.0.0',
|
||||
pnpmHomeDir: process.cwd(),
|
||||
rawConfig: {},
|
||||
})
|
||||
expect(exitCode).toBe(0)
|
||||
expect(fs.readFileSync('version', 'utf8')).toBe('v14.0.0')
|
||||
@@ -22,6 +23,7 @@ test('run LTS version of Node.js by default', async () => {
|
||||
original: ['node', '-e', 'require("fs").writeFileSync("version",process.version, "utf8")'],
|
||||
},
|
||||
pnpmHomeDir: process.cwd(),
|
||||
rawConfig: {},
|
||||
})
|
||||
expect(exitCode).toBe(0)
|
||||
expect(fs.readFileSync('version', 'utf8')).toMatch(/^v[0-9]+\.[0-9]+\.[0-9]+$/)
|
||||
|
||||
@@ -15,8 +15,17 @@
|
||||
{
|
||||
"path": "../cli-utils"
|
||||
},
|
||||
{
|
||||
"path": "../config"
|
||||
},
|
||||
{
|
||||
"path": "../fetch"
|
||||
},
|
||||
{
|
||||
"path": "../package-store"
|
||||
},
|
||||
{
|
||||
"path": "../tarball-fetcher"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -228,7 +228,7 @@ export default async function run (inputArgv: string[]) {
|
||||
|
||||
try {
|
||||
if (config.useNodeVersion != null) {
|
||||
const nodePath = path.join(await node.getNodeDir(config.pnpmHomeDir, config.useNodeVersion), 'node_modules/.bin')
|
||||
const nodePath = await node.getNodeDir(config)
|
||||
config.extraBinPaths.push(nodePath)
|
||||
}
|
||||
let result = pnpmCmds[cmd ?? 'help'](
|
||||
|
||||
@@ -211,9 +211,8 @@ function isGitHostedPkgUrl (url: string) {
|
||||
) && url.includes('tar.gz')
|
||||
}
|
||||
|
||||
async function prepareGitHostedPkg (filesIndex: FilesIndex, cafs: Cafs) {
|
||||
const tempLocation = await cafs.tempDir()
|
||||
const filesIndexReady: Record<string, PackageFileInfo> = R.fromPairs(
|
||||
export async function waitForFilesIndex (filesIndex: FilesIndex): Promise<Record<string, PackageFileInfo>> {
|
||||
return R.fromPairs(
|
||||
await Promise.all(
|
||||
Object.entries(filesIndex).map(async ([fileName, fileInfo]): Promise<[string, PackageFileInfo]> => {
|
||||
const { integrity, checkedAt } = await fileInfo.writeResult
|
||||
@@ -228,9 +227,13 @@ async function prepareGitHostedPkg (filesIndex: FilesIndex, cafs: Cafs) {
|
||||
})
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
async function prepareGitHostedPkg (filesIndex: FilesIndex, cafs: Cafs) {
|
||||
const tempLocation = await cafs.tempDir()
|
||||
await cafs.importPackage(tempLocation, {
|
||||
filesResponse: {
|
||||
filesIndex: filesIndexReady,
|
||||
filesIndex: await waitForFilesIndex(filesIndex),
|
||||
fromStore: false,
|
||||
},
|
||||
force: true,
|
||||
|
||||
@@ -17,11 +17,12 @@ import ssri from 'ssri'
|
||||
import createDownloader, {
|
||||
DownloadFunction,
|
||||
TarballIntegrityError,
|
||||
waitForFilesIndex,
|
||||
} from './createDownloader'
|
||||
|
||||
export { BadTarballError } from './errorTypes'
|
||||
|
||||
export { TarballIntegrityError }
|
||||
export { TarballIntegrityError, waitForFilesIndex }
|
||||
|
||||
export default function (
|
||||
fetchFromRegistry: FetchFromRegistry,
|
||||
|
||||
37
pnpm-lock.yaml
generated
37
pnpm-lock.yaml
generated
@@ -1928,25 +1928,41 @@ importers:
|
||||
packages/plugin-commands-nvm:
|
||||
specifiers:
|
||||
'@pnpm/cli-utils': workspace:0.6.5
|
||||
'@pnpm/config': workspace:12.3.0
|
||||
'@pnpm/fetch': workspace:3.1.0
|
||||
'@pnpm/package-store': workspace:12.0.7
|
||||
'@pnpm/plugin-commands-nvm': 'link:'
|
||||
'@pnpm/prepare': workspace:0.0.23
|
||||
'@pnpm/store-path': ^5.0.0
|
||||
'@pnpm/tarball-fetcher': workspace:9.2.2
|
||||
'@types/adm-zip': ^0.4.34
|
||||
adm-zip: ^0.5.5
|
||||
execa: ^5.0.0
|
||||
load-json-file: ^6.2.0
|
||||
path-name: ^1.0.0
|
||||
rename-overwrite: ^4.0.0
|
||||
render-help: ^1.0.1
|
||||
tempy: ^1.0.0
|
||||
write-json-file: ^4.3.0
|
||||
dependencies:
|
||||
'@pnpm/cli-utils': link:../cli-utils
|
||||
'@pnpm/config': link:../config
|
||||
'@pnpm/fetch': link:../fetch
|
||||
'@pnpm/package-store': link:../package-store
|
||||
'@pnpm/store-path': 5.0.0
|
||||
'@pnpm/tarball-fetcher': link:../tarball-fetcher
|
||||
adm-zip: 0.5.5
|
||||
execa: 5.0.0
|
||||
load-json-file: 6.2.0
|
||||
path-name: 1.0.0
|
||||
rename-overwrite: 4.0.0
|
||||
render-help: 1.0.2
|
||||
tempy: 1.0.1
|
||||
write-json-file: 4.3.0
|
||||
devDependencies:
|
||||
'@pnpm/plugin-commands-nvm': 'link:'
|
||||
'@pnpm/prepare': link:../../privatePackages/prepare
|
||||
'@types/adm-zip': 0.4.34
|
||||
|
||||
packages/plugin-commands-outdated:
|
||||
specifiers:
|
||||
@@ -4573,6 +4589,12 @@ packages:
|
||||
resolution: {integrity: sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==}
|
||||
engines: {node: '>= 6'}
|
||||
|
||||
/@types/adm-zip/0.4.34:
|
||||
resolution: {integrity: sha512-8ToYLLAYhkRfcmmljrKi22gT2pqu7hGMDtORP1emwIEGmgUTZOsaDjzWFzW5N2frcFRz/50CWt4zA1CxJ73pmQ==}
|
||||
dependencies:
|
||||
'@types/node': 15.6.1
|
||||
dev: true
|
||||
|
||||
/@types/archy/0.0.31:
|
||||
resolution: {integrity: sha512-v+dxizsFVyXgD3EpFuqT9YjdEjbJmPxNf1QIX9ohZOhxh1ZF2yhqv3vYaeum9lg3VghhxS5S0a6yldN9J9lPEQ==}
|
||||
dev: true
|
||||
@@ -4773,6 +4795,10 @@ packages:
|
||||
/@types/node/15.3.0:
|
||||
resolution: {integrity: sha512-8/bnjSZD86ZfpBsDlCIkNXIvm+h6wi9g7IqL+kmFkQ+Wvu3JrasgLElfiPgoo8V8vVfnEi0QVS12gbl94h9YsQ==}
|
||||
|
||||
/@types/node/15.6.1:
|
||||
resolution: {integrity: sha512-7EIraBEyRHEe7CH+Fm1XvgqU6uwZN8Q7jppJGcqjROMT29qhAuuOxYB1uEY5UMYQKEmA5D+5tBnhdaPXSsLONA==}
|
||||
dev: true
|
||||
|
||||
/@types/nopt/3.0.29:
|
||||
resolution: {integrity: sha1-8Z3z20yX7hRZonQAKDIKcdcJZM4=}
|
||||
dev: true
|
||||
@@ -5295,6 +5321,11 @@ packages:
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/adm-zip/0.5.5:
|
||||
resolution: {integrity: sha512-IWwXKnCbirdbyXSfUDvCCrmYrOHANRZcc8NcRrvTlIApdl7PwE9oGcsYvNeJPAVY1M+70b4PxXGKIf8AEuiQ6w==}
|
||||
engines: {node: '>=6.0'}
|
||||
dev: false
|
||||
|
||||
/agent-base/4.3.0:
|
||||
resolution: {integrity: sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==}
|
||||
engines: {node: '>= 4.0.0'}
|
||||
@@ -7062,7 +7093,6 @@ packages:
|
||||
p-map: 4.0.0
|
||||
rimraf: 3.0.2
|
||||
slash: 3.0.0
|
||||
dev: true
|
||||
|
||||
/delay/5.0.0:
|
||||
resolution: {integrity: sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==}
|
||||
@@ -9093,12 +9123,10 @@ packages:
|
||||
/is-path-cwd/2.2.0:
|
||||
resolution: {integrity: sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==}
|
||||
engines: {node: '>=6'}
|
||||
dev: true
|
||||
|
||||
/is-path-inside/3.0.3:
|
||||
resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==}
|
||||
engines: {node: '>=8'}
|
||||
dev: true
|
||||
|
||||
/is-plain-obj/1.1.0:
|
||||
resolution: {integrity: sha1-caUMhCnfync8kqOQpKA7OfzVHT4=}
|
||||
@@ -13215,7 +13243,6 @@ packages:
|
||||
/temp-dir/2.0.0:
|
||||
resolution: {integrity: sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==}
|
||||
engines: {node: '>=8'}
|
||||
dev: true
|
||||
|
||||
/tempy/1.0.1:
|
||||
resolution: {integrity: sha512-biM9brNqxSc04Ee71hzFbryD11nX7VPhQQY32AdDmjFvodsRFz/3ufeoTZ6uYkRFfGo188tENcASNs3vTdsM0w==}
|
||||
@@ -13226,7 +13253,6 @@ packages:
|
||||
temp-dir: 2.0.0
|
||||
type-fest: 0.16.0
|
||||
unique-string: 2.0.0
|
||||
dev: true
|
||||
|
||||
/term-size/1.2.0:
|
||||
resolution: {integrity: sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=}
|
||||
@@ -13626,7 +13652,6 @@ packages:
|
||||
/type-fest/0.16.0:
|
||||
resolution: {integrity: sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==}
|
||||
engines: {node: '>=10'}
|
||||
dev: true
|
||||
|
||||
/type-fest/0.18.1:
|
||||
resolution: {integrity: sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==}
|
||||
|
||||
Reference in New Issue
Block a user