forked from pnpm/pnpm
/
node.ts
99 lines (94 loc) · 3.2 KB
/
node.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import fs from 'fs'
import path from 'path'
import { Config } from '@pnpm/config'
import { createFetchFromRegistry, FetchFromRegistry } from '@pnpm/fetch'
import { globalInfo } from '@pnpm/logger'
import { fetchNode } from '@pnpm/node.fetcher'
import storePath from '@pnpm/store-path'
import loadJsonFile from 'load-json-file'
import writeJsonFile from 'write-json-file'
import getNodeMirror from './getNodeMirror'
import { parseNodeEditionSpecifier } from './parseNodeEditionSpecifier'
export type NvmNodeCommandOptions = Pick<Config,
| 'bin'
| 'global'
| 'fetchRetries'
| 'fetchRetryFactor'
| 'fetchRetryMaxtimeout'
| 'fetchRetryMintimeout'
| 'fetchTimeout'
| 'userAgent'
| 'ca'
| 'cert'
| 'httpProxy'
| 'httpsProxy'
| 'key'
| 'localAddress'
| 'noProxy'
| 'rawConfig'
| 'strictSsl'
| 'storeDir'
| 'useNodeVersion'
| 'pnpmHomeDir'
> & Partial<Pick<Config, 'configDir'>>
export async function getNodeBinDir (opts: NvmNodeCommandOptions) {
const fetch = createFetchFromRegistry(opts)
const nodesDir = getNodeVersionsBaseDir(opts.pnpmHomeDir)
let wantedNodeVersion = opts.useNodeVersion ?? (await readNodeVersionsManifest(nodesDir))?.default
if (wantedNodeVersion == null) {
const response = await fetch('https://registry.npmjs.org/node')
wantedNodeVersion = (await response.json() as any)['dist-tags'].lts // eslint-disable-line
if (wantedNodeVersion == null) {
throw new Error('Could not resolve LTS version of Node.js')
}
await writeJsonFile(path.join(nodesDir, 'versions.json'), {
default: wantedNodeVersion,
})
}
const { versionSpecifier, releaseChannel } = parseNodeEditionSpecifier(wantedNodeVersion)
const nodeMirrorBaseUrl = getNodeMirror(opts.rawConfig, releaseChannel)
const nodeDir = await getNodeDir(fetch, {
...opts,
useNodeVersion: versionSpecifier,
nodeMirrorBaseUrl,
})
return process.platform === 'win32' ? nodeDir : path.join(nodeDir, 'bin')
}
function getNodeVersionsBaseDir (pnpmHomeDir: string) {
return path.join(pnpmHomeDir, 'nodejs')
}
export async function getNodeDir (fetch: FetchFromRegistry, opts: NvmNodeCommandOptions & { useNodeVersion: string, nodeMirrorBaseUrl: string }) {
const nodesDir = getNodeVersionsBaseDir(opts.pnpmHomeDir)
await fs.promises.mkdir(nodesDir, { recursive: true })
const versionDir = path.join(nodesDir, opts.useNodeVersion)
if (!fs.existsSync(versionDir)) {
const storeDir = await storePath({
pkgRoot: process.cwd(),
storePath: opts.storeDir,
pnpmHomeDir: opts.pnpmHomeDir,
})
const cafsDir = path.join(storeDir, 'files')
globalInfo(`Fetching Node.js ${opts.useNodeVersion} ...`)
await fetchNode(fetch, opts.useNodeVersion, versionDir, {
...opts,
cafsDir,
retry: {
maxTimeout: opts.fetchRetryMaxtimeout,
minTimeout: opts.fetchRetryMintimeout,
retries: opts.fetchRetries,
factor: opts.fetchRetryFactor,
},
})
}
return versionDir
}
async function readNodeVersionsManifest (nodesDir: string): Promise<{ default?: string }> {
try {
return await loadJsonFile<{ default?: string }>(path.join(nodesDir, 'versions.json'))
} catch (err: any) { // eslint-disable-line
if (err.code === 'ENOENT') {
return {}
}
throw err
}
}