forked from tabrindle/install-subset
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
executable file
·159 lines (134 loc) · 4.87 KB
/
index.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
148
149
150
151
152
153
154
155
156
157
158
159
#!/usr/bin/env node
'use strict';
var path = require('path');
var fs = require('fs');
var shelljs = require('shelljs');
var cli = require('commander');
var cwd = process.cwd();
var installSubsetPackageJson = require('./package.json');
var packageJson = require(cwd + '/package.json');
var spawnSync = require('cross-spawn').sync;
var backup = function(filename) {
try {
const originalPath = path.join(cwd, filename)
const backupPath = originalPath + '.backup'
fs.writeFileSync(backupPath, fs.readFileSync(originalPath));
} catch (err) {}
};
var restore = function(filename) {
try {
const originalPath = path.join(cwd, filename)
const backupPath = originalPath + '.backup'
fs.writeFileSync(originalPath, fs.readFileSync(backupPath));
fs.unlinkSync(backupPath);
} catch (err) {}
};
var omit = function(obj, props) {
return Object.keys(obj)
.filter(key => props.indexOf(key) < 0)
.reduce((acc, key) => Object.assign(acc, { [key]: obj[key] }), {});
};
var pick = function(obj, props) {
return Object.keys(obj)
.filter(key => props.indexOf(key) >= 0)
.reduce((acc, key) => Object.assign(acc, { [key]: obj[key] }), {});
};
cli
.command('install <input_strings...>')
.alias('i')
.option('-d, --clean', 'Remove node_modules first.')
.option('--npm', 'Use npm to install.')
.option('-a, --all', 'Prune dependencies as well as devDependencies.')
.description('Install a given subset or multiple subsets defined in package.json.')
.action(function(input_strings, options) {
if (!packageJson.subsets) {
console.error('No install subsets in package.json.')
process.exit(1)
}
const subsetStrings = []
if (input_strings.length >= 1) {
for (let string of input_strings) {
subsetStrings.push(string)
}
}
let subset = {}
for(var i=0; i < subsetStrings.length; i++) {
const packageSubset = packageJson.subsets[subsetStrings[i]]
if (!packageSubset) {
console.error(`No install subset with name ${subsetStrings[i]} was found.`)
process.exit(1)
}
if (packageSubset.exclude) {
if (!subset.exclude) {
subset.exclude = []
}
subset.exclude = [...subset.exclude, ...packageSubset.exclude]
}
if (packageSubset.include) {
if (!subset.include) {
subset.include = []
}
subset.include = [...subset.include, ...packageSubset.include]
}
}
if (subset.include && subset.exclude) {
console.error(`Failed to install subset ${input_string}.`);
console.error("Subsets can only include OR exclude packages. Please correct your subset or combination of subsets and try again.")
process.exit(1)
}
// prune devDependencies according to subset declarations and options
if (subset.include) {
packageJson.devDependencies = pick(packageJson.devDependencies, subset.include);
} else if (subset.exclude) {
packageJson.devDependencies = omit(packageJson.devDependencies, subset.exclude);
} else {
console.error('No valid subset actions found.')
process.exit(1)
}
if (options.all) {
// prune dependencies according to subset declarations and options
if (subset.include) {
packageJson.dependencies = pick(packageJson.dependencies, subset.include);
} else if (subset.exclude) {
packageJson.dependencies = omit(packageJson.dependencies, subset.exclude);
} else {
console.error('No valid subset actions found.')
process.exit(1)
}
}
// backup package.json and lockfiles to restore later
backup('package.json');
backup('package-lock.json');
backup('yarn.lock');
if (options.clean) {
shelljs.rm('-rf', path.join(cwd, 'node_modules'));
}
try {
// write the new temp package.json
fs.writeFileSync(path.join(cwd, 'package.json'), JSON.stringify(packageJson, null, ' '));
// choose which installer to use, then spawn
if (!options.npm && shelljs.which('yarn')) {
var installer = spawnSync('yarn', ['install'], { stdio: 'inherit' });
} else {
var installer = spawnSync('npm', ['install'], { stdio: 'inherit' });
}
} catch (err) {} // err doesn't matter, need to perform cleanup operations
// restore package.json and lockfiles from backup
restore('package.json');
restore('package-lock.json');
restore('yarn.lock');
if (installer.status !== 0) {
console.error(`Error code ${installer.status}.`)
process.exit(1)
}
for (let input_string of subsetStrings) {
console.log(`Installation of subset ${input_string} successful.`);
}
});
cli.command('*').action(() => cli.help());
cli.version(installSubsetPackageJson.version).parse(process.argv);
if (cli.args.length === 0) cli.help();
process.on('uncaughtException', err => {
console.error('ERROR: ' + err);
process.exit(1)
});