-
Notifications
You must be signed in to change notification settings - Fork 416
/
npm.js
147 lines (124 loc) · 4.18 KB
/
npm.js
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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
'use strict';
/**
* NPM packager.
*/
const _ = require('lodash');
const BbPromise = require('bluebird');
const Utils = require('../utils');
const { join } = require('path');
const fse = require('fs-extra');
const fs = require('fs');
class NPM {
// eslint-disable-next-line lodash/prefer-constant
static get lockfileName() {
return 'package-lock.json';
}
static get copyPackageSectionNames() {
return [];
}
// eslint-disable-next-line lodash/prefer-constant
static get mustCopyModules() {
return true;
}
static getProdDependencies(cwd, depth, packagerOptions) {
// Try to use NPM lockfile v2 when possible
const options = packagerOptions || {};
const lockPath = join(cwd, options.lockFile || NPM.lockfileName);
if (fse.pathExistsSync(lockPath)) {
const lock = Utils.safeJsonParse(fs.readFileSync(lockPath));
if (lock.lockfileVersion === 2) {
return BbPromise.resolve(lock);
}
}
// Get first level dependency graph
const command = /^win/.test(process.platform) ? 'npm.cmd' : 'npm';
const args = [
'ls',
'-prod', // Only prod dependencies
'-json',
`-depth=${depth || 1}`
];
const ignoredNpmErrors = [
{ npmError: 'code ELSPROBLEMS', log: false }, // npm >= 7
{ npmError: 'extraneous', log: false },
{ npmError: 'missing', log: false },
{ npmError: 'peer dep missing', log: true }
];
return Utils.spawnProcess(command, args, {
cwd: cwd
})
.catch(err => {
if (err instanceof Utils.SpawnError) {
// Only exit with an error if we have critical npm errors for 2nd level inside
// ignoring any extra output from npm >= 7
const lines = _.split(err.stderr, '\n');
const errors = _.takeWhile(lines, line => line !== '{');
const failed = _.reduce(
errors,
(failed, error) => {
if (failed) {
return true;
}
return (
!_.isEmpty(error) &&
!_.some(ignoredNpmErrors, ignoredError => _.startsWith(error, `npm ERR! ${ignoredError.npmError}`))
);
},
false
);
if (!failed && !_.isEmpty(err.stdout)) {
return BbPromise.resolve({ stdout: err.stdout });
}
}
return BbPromise.reject(err);
})
.then(processOutput => processOutput.stdout)
.then(depJson => BbPromise.try(() => JSON.parse(depJson)));
}
static _rebaseFileReferences(pathToPackageRoot, moduleVersion) {
if (/^file:[^/]{2}/.test(moduleVersion)) {
const filePath = _.replace(moduleVersion, /^file:/, '');
return _.replace(`file:${pathToPackageRoot}/${filePath}`, /\\/g, '/');
}
return moduleVersion;
}
/**
* We should not be modifying 'package-lock.json'
* because this file should be treated as internal to npm.
*
* Rebase package-lock is a temporary workaround and must be
* removed as soon as https://github.com/npm/npm/issues/19183 gets fixed.
*/
static rebaseLockfile(pathToPackageRoot, lockfile) {
if (lockfile.version) {
lockfile.version = NPM._rebaseFileReferences(pathToPackageRoot, lockfile.version);
}
if (lockfile.dependencies) {
_.forIn(lockfile.dependencies, lockedDependency => {
NPM.rebaseLockfile(pathToPackageRoot, lockedDependency);
});
}
return lockfile;
}
static install(cwd, packagerOptions) {
if (packagerOptions.noInstall) {
return BbPromise.resolve();
}
const command = /^win/.test(process.platform) ? 'npm.cmd' : 'npm';
const args = ['install'];
return Utils.spawnProcess(command, args, { cwd }).return();
}
static prune(cwd) {
const command = /^win/.test(process.platform) ? 'npm.cmd' : 'npm';
const args = ['prune'];
return Utils.spawnProcess(command, args, { cwd }).return();
}
static runScripts(cwd, scriptNames) {
const command = /^win/.test(process.platform) ? 'npm.cmd' : 'npm';
return BbPromise.mapSeries(scriptNames, scriptName => {
const args = ['run', scriptName];
return Utils.spawnProcess(command, args, { cwd });
}).return();
}
}
module.exports = NPM;