UNPKG

3.4 kBJavaScriptView Raw
1var path = require('path')
2var util = require('util')
3var Transform = require('stream').Transform
4var multimatch = require('multimatch')
5var objectEach = require('mixy').each
6
7util.inherits(Groups, Transform)
8
9module.exports = Groups
10
11var UNKNOWN = '__UNKNOWN__'
12var noop = function () {}
13
14function Groups(opts) {
15 Transform.call(this, { objectMode: true })
16
17 opts = opts || {}
18 this.basedir = opts.basedir || process.cwd()
19 this._groupFilters = [].concat(opts.groupFilter)
20 .filter(Boolean).map(this.createFilter, this)
21
22 this._groups = Object.create(null)
23 this._bundles = Object.create(null)
24 this._unknown = []
25}
26
27Groups.prototype._transform = function(row, _, next) {
28 var moduleID = row.id
29 this.getGroups(row).forEach(function (group) {
30 this._bundles[group] = true
31 this._addGroup(moduleID, group)
32 }, this)
33
34 // Ensure that `this._groups[moduleID]` is ready
35 this._addGroup(moduleID)
36
37 var groups = Object.keys(this._groups[moduleID])
38 if (!groups.length) {
39 groups.push(UNKNOWN)
40 }
41
42 groups.forEach(function (group) {
43 this.addGroup(row, group)
44 }, this)
45
46 next(null, row)
47}
48
49Groups.prototype._flush = function(next) {
50 var bundles = Object.keys(this._bundles)
51 this._unknown.forEach(function (moduleID) {
52 bundles.forEach(function (bundleID) {
53 this._addGroup(moduleID, bundleID)
54 }, this)
55 }, this)
56
57 var groups = this._groups
58 this.emit('groups', bundles.reduce(function (map, bundleID) {
59 var modules = map[bundleID] = []
60 objectEach(groups, function (bundleMap, moduleID) {
61 if (bundleMap[bundleID]) {
62 modules.push(moduleID)
63 }
64 })
65 return map
66 }, Object.create(null)))
67
68 next()
69}
70
71Groups.prototype._addGroup = function(moduleID, group) {
72 var groups = this._groups[moduleID]
73 if (!groups) {
74 groups = Object.create(null)
75 }
76 if (group) {
77 groups[group] = true
78 }
79 this._groups[moduleID] = groups
80}
81
82Groups.prototype.addGroup = function(row, group) {
83 Object.keys(row.deps || {}).forEach(function (key) {
84 this._addGroup(row.deps[key], group)
85 }, this)
86
87 var moduleID = row.id
88
89 if (this._groups[moduleID][UNKNOWN]) {
90 delete this._groups[moduleID][UNKNOWN]
91 }
92
93 if (group === UNKNOWN) {
94 this._unknown.push(moduleID)
95 }
96}
97
98Groups.prototype.createFilter = function(opts) {
99 if (typeof opts === 'function') {
100 opts = { output: opts }
101 } else if (typeof opts === 'string' || Array.isArray(opts)) {
102 opts = { filter: opts }
103 }
104 if (typeof opts !== 'object') return noop
105 var basedir = opts.basedir || this.basedir
106 if (typeof opts.output === 'function') {
107 return function (file) {
108 return path.relative(
109 basedir,
110 path.resolve(basedir, opts.output(file))
111 )
112 }
113 }
114
115 var output = opts.output
116 if (typeof output === 'string') {
117 output = path.relative(
118 basedir,
119 path.resolve(basedir, output)
120 )
121 } else {
122 output = null
123 }
124 var filterEntries = opts.filter
125 if (typeof filterEntries !== 'function') {
126 filterEntries = function (file) {
127 if (!opts.filter) return true
128 return multimatch(file, opts.filter).length
129 }
130 }
131 return function (file) {
132 if (filterEntries(file)) {
133 return output || path.relative(basedir, file)
134 }
135 }
136}
137
138Groups.prototype.getGroups = function(row) {
139 return this._groupFilters.map(function (filter) {
140 return filter(row.file)
141 }).filter(Boolean)
142}
143