1 | const spawn = require('cross-spawn')
|
2 | const logUpdate = require('log-update')
|
3 | const spinner = require('./spinner')
|
4 | const logger = require('./logger')
|
5 | const SAOError = require('./SAOError')
|
6 |
|
7 | let cachedNpmClient = null
|
8 |
|
9 | function setNpmClient(npmClient) {
|
10 | cachedNpmClient = npmClient
|
11 | }
|
12 |
|
13 | function 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 |
|
27 | module.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 |
|
40 |
|
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 |
|
63 | npm_config_color: 'always',
|
64 | npm_config_progress: true
|
65 |
|
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 |
|
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 |
|
117 | module.exports.getNpmClient = getNpmClient
|
118 | module.exports.setNpmClient = setNpmClient
|