UNPKG

2.85 kBJavaScriptView Raw
1const spawn = require('cross-spawn')
2const logUpdate = require('log-update')
3const spinner = require('./spinner')
4const logger = require('./logger')
5const SAOError = require('./SAOError')
6
7let cachedNpmClient = null
8
9function setNpmClient(npmClient) {
10 cachedNpmClient = npmClient
11}
12
13function getNpmClient() {
14 if (cachedNpmClient) {
15 return cachedNpmClient
16 }
17
18 if (spawn.sync('pnpm', ['--version']).status === 0) {
19 cachedNpmClient = 'pnpm'
20 } else if (spawn.sync('yarn', ['--version']).status === 0) {
21 cachedNpmClient = 'yarn'
22 }
23
24 return cachedNpmClient
25}
26
27module.exports = async ({
28 cwd,
29 npmClient,
30 installArgs,
31 packages,
32 saveDev,
33 registry
34}) => {
35 npmClient = npmClient || getNpmClient()
36 const packageName = packages ? packages.join(', ') : 'packages'
37
38 return new Promise((resolve, reject) => {
39 // `npm/pnpm/yarn add <packages>`
40 // `npm/pnpm/yarn install`
41 const args = [packages ? 'add' : 'install'].concat(packages ? packages : [])
42 if (saveDev) {
43 args.push(npmClient === 'npm' ? '-D' : '--dev')
44 }
45 if (registry) {
46 args.push('--registry', registry)
47 }
48
49 if (installArgs) {
50 args.push(...installArgs)
51 }
52
53 logger.debug(npmClient, args.join(' '))
54 logger.debug('install directory', cwd)
55 spinner.start(`Installing ${packageName} with ${npmClient}`)
56 const ps = spawn(npmClient, args, {
57 stdio: [0, 'pipe', 'pipe'],
58 cwd,
59 env: Object.assign(
60 {
61 FORCE_COLOR: true,
62 /* eslint-disable camelcase */
63 npm_config_color: 'always',
64 npm_config_progress: true
65 /* eslint-enable camelcase */
66 },
67 process.env
68 )
69 })
70
71 let stdoutLogs = ''
72 let stderrLogs = ''
73
74 ps.stdout &&
75 ps.stdout.setEncoding('utf8').on('data', data => {
76 if (npmClient === 'pnpm') {
77 stdoutLogs = data
78 } else {
79 stdoutLogs += data
80 }
81 spinner.stop()
82 logUpdate(stdoutLogs)
83 spinner.start()
84 })
85
86 ps.stderr &&
87 ps.stderr.setEncoding('utf8').on('data', data => {
88 if (npmClient === 'pnpm') {
89 stderrLogs = data
90 } else {
91 stderrLogs += data
92 }
93 spinner.stop()
94 logUpdate.clear()
95 logUpdate.stderr(stderrLogs)
96 logUpdate(stdoutLogs)
97 spinner.start()
98 })
99
100 ps.on('close', code => {
101 spinner.stop()
102 // Clear output when succeeded
103 if (code === 0) {
104 logUpdate.clear()
105 logUpdate.stderr.clear()
106 logger.success(`Installed ${packageName}`)
107 } else {
108 throw new SAOError(`Failed to install ${packageName} in ${cwd}`)
109 }
110 resolve({ code, npmClient })
111 })
112
113 ps.on('error', reject)
114 })
115}
116
117module.exports.getNpmClient = getNpmClient
118module.exports.setNpmClient = setNpmClient