1 | var path = require('path')
|
2 | var util = require('util')
|
3 | var Transform = require('stream').Transform
|
4 | var multimatch = require('multimatch')
|
5 | var objectEach = require('mixy').each
|
6 |
|
7 | util.inherits(Groups, Transform)
|
8 |
|
9 | module.exports = Groups
|
10 |
|
11 | var UNKNOWN = '__UNKNOWN__'
|
12 | var noop = function () {}
|
13 |
|
14 | function 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 |
|
27 | Groups.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 |
|
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 |
|
49 | Groups.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 |
|
71 | Groups.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 |
|
82 | Groups.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 |
|
98 | Groups.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 | if (typeof opts.output === 'function') return opts.output
|
106 |
|
107 | var output = opts.output
|
108 | if (typeof output !== 'string') output = null
|
109 | var filterEntries = opts.filter
|
110 | if (typeof filterEntries !== 'function') {
|
111 | filterEntries = function (file) {
|
112 | if (!opts.filter) return true
|
113 | return multimatch(file, opts.filter).length
|
114 | }
|
115 | }
|
116 | var basedir = opts.basedir || this.basedir
|
117 | return function (file) {
|
118 | if (filterEntries(file)) {
|
119 | return output || path.relative(basedir, file)
|
120 | }
|
121 | }
|
122 | }
|
123 |
|
124 | Groups.prototype.getGroups = function(row) {
|
125 | return this._groupFilters.map(function (filter) {
|
126 | return filter(row.file)
|
127 | }).filter(Boolean)
|
128 | }
|
129 |
|