/
filter-packages.js
75 lines (60 loc) · 2.11 KB
/
filter-packages.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
"use strict";
const util = require("util");
const multimatch = require("multimatch");
const log = require("npmlog");
const ValidationError = require("@lerna/validation-error");
module.exports = filterPackages;
/**
* Filters a given set of packages and returns all packages that match the scope glob
* and do not match the ignore glob
*
* @param {!Array.<Package>} packagesToFilter The packages to filter
* @param {Array.<String>} include A list of globs to match the package name against
* @param {Array.<String>} exclude A list of globs to filter the package name against
* @param {Boolean} showPrivate When false, filter out private packages
* @param {Boolean} continueIfNoMatch When true, do not throw if no package is matched
* @return {Array.<Package>} The packages with a name matching the glob
* @throws when a given glob would produce an empty list of packages and `continueIfNoMatch` is not set.
*/
function filterPackages(packagesToFilter, include = [], exclude = [], showPrivate, continueIfNoMatch) {
const filtered = new Set(packagesToFilter);
const patterns = [].concat(arrify(include), negate(exclude));
if (showPrivate === false) {
for (const pkg of filtered) {
if (pkg.private) {
filtered.delete(pkg);
}
}
}
if (patterns.length) {
log.info("filter", patterns);
if (!include.length) {
// only excludes needs to select all items first
// globstar is for matching scoped packages
patterns.unshift("**");
}
const pnames = Array.from(filtered).map(pkg => pkg.name);
const chosen = new Set(multimatch(pnames, patterns));
for (const pkg of filtered) {
if (!chosen.has(pkg.name)) {
filtered.delete(pkg);
}
}
if (!filtered.size && !continueIfNoMatch) {
throw new ValidationError("EFILTER", util.format("No packages remain after filtering", patterns));
}
}
return Array.from(filtered);
}
function arrify(thing) {
if (!thing) {
return [];
}
if (!Array.isArray(thing)) {
return [thing];
}
return thing;
}
function negate(patterns) {
return arrify(patterns).map(pattern => `!${pattern}`);
}