UNPKG

3.27 kBJavaScriptView Raw
1var through = require('through2');
2var shasum = require('shasum');
3var isarray = require('isarray');
4
5module.exports = function (opts) {
6 if (!opts) opts = {};
7 var rows = [];
8 return through.obj(write, end);
9
10 function write (row, enc, next) { rows.push(row); next() }
11
12 function end () {
13 var tr = this;
14 rows.sort(cmp);
15 sorter(rows, tr, opts);
16 }
17};
18
19function sorter (rows, tr, opts) {
20 var expose = opts.expose || {};
21 if (isarray(expose)) {
22 expose = expose.reduce(function (acc, key) {
23 acc[key] = true;
24 return acc;
25 }, {});
26 }
27
28 var hashes = {}, deduped = {};
29 var sameDeps = depCmp();
30
31 if (opts.dedupe) {
32 rows.forEach(function (row) {
33 var h = shasum(row.source);
34 sameDeps.add(row, h);
35 if (hashes[h]) {
36 hashes[h].push(row);
37 } else {
38 hashes[h] = [row];
39 }
40 });
41 Object.keys(hashes).forEach(function (h) {
42 var rows = hashes[h];
43 while (rows.length > 1) {
44 var row = rows.pop();
45 row.dedupe = rows[0].id;
46 row.sameDeps = sameDeps.cmp(rows[0].deps, row.deps);
47 deduped[row.id] = rows[0].id;
48 }
49 });
50 }
51
52 if (opts.index) {
53 var index = {};
54 var offset = 0;
55 rows.forEach(function (row, ix) {
56 if (has(expose, row.id)) {
57 row.index = row.id;
58 offset ++;
59 if (expose[row.id] !== true) {
60 index[expose[row.id]] = row.index;
61 }
62 }
63 else {
64 row.index = ix + 1 - offset;
65 }
66 index[row.id] = row.index;
67 });
68 rows.forEach(function (row) {
69 row.indexDeps = {};
70 Object.keys(row.deps).forEach(function (key) {
71 var id = row.deps[key];
72 row.indexDeps[key] = index[id];
73 });
74 if (row.dedupe) {
75 row.dedupeIndex = index[row.dedupe];
76 }
77 tr.push(row);
78 });
79 }
80 else {
81 rows.forEach(function (row) { tr.push(row) });
82 }
83 tr.push(null);
84};
85
86function cmp (a, b) {
87 return a.id + a.hash < b.id + b.hash ? -1 : 1;
88}
89
90function has (obj, key) {
91 return Object.prototype.hasOwnProperty.call(obj, key);
92}
93
94function depCmp (hashes) {
95 var deps = {}, hashes = {};
96 return { add: add, cmp: cmp }
97
98 function add (row, hash) {
99 deps[row.id] = row.deps;
100 hashes[row.id] = hash;
101 }
102 function cmp (a, b, limit) {
103 if (!a && !b) return true;
104 if (!a || !b) return false;
105
106 var keys = Object.keys(a);
107 if (keys.length !== Object.keys(b).length) return false;
108
109 for (var i = 0; i < keys.length; i++) {
110 var k = keys[i], ka = a[k], kb = b[k];
111 var ha = hashes[ka];
112 var hb = hashes[kb];
113 var da = deps[ka];
114 var db = deps[kb];
115
116 if (ka === kb) continue;
117 if (ha !== hb || (!limit && !cmp(da, db, 1))) {
118 return false;
119 }
120 }
121 return true;
122 }
123}