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