File: index.js

package info (click to toggle)
node-deps-sort 2.0.0-2
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 140 kB
  • sloc: makefile: 23; sh: 13
file content (122 lines) | stat: -rw-r--r-- 3,235 bytes parent folder | download | duplicates (3)
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
var through = require('through2');
var shasum = require('shasum');

module.exports = function (opts) {
    if (!opts) opts = {};
    var rows = [];
    return through.obj(write, end);
    
    function write (row, enc, next) { rows.push(row); next() }
    
    function end () {
        var tr = this;
        rows.sort(cmp);
        sorter(rows, tr, opts);
    }
};

function sorter (rows, tr, opts) {
    var expose = opts.expose || {};
    if (Array.isArray(expose)) {
        expose = expose.reduce(function (acc, key) {
            acc[key] = true;
            return acc;
        }, {});
    }
    
    var hashes = {}, deduped = {};
    var sameDeps = depCmp();
    
    if (opts.dedupe) {
        rows.forEach(function (row) {
            var h = shasum(row.source);
            sameDeps.add(row, h);
            if (hashes[h]) {
                hashes[h].push(row);
            } else {
                hashes[h] = [row];
            }
        });
        Object.keys(hashes).forEach(function (h) {
            var rows = hashes[h];
            while (rows.length > 1) {
                var row = rows.pop();
                row.dedupe = rows[0].id;
                row.sameDeps = sameDeps.cmp(rows[0].deps, row.deps);
                deduped[row.id] = rows[0].id;
            }
        });
    }
    
    if (opts.index) {
        var index = {};
        var offset = 0;
        rows.forEach(function (row, ix) {
            if (has(expose, row.id)) {
                row.index = row.id;
                offset ++;
                if (expose[row.id] !== true) {
                    index[expose[row.id]] = row.index;
                }
            }
            else {
                row.index = ix + 1 - offset;
            }
            index[row.id] = row.index;
        });
        rows.forEach(function (row) {
            row.indexDeps = {};
            Object.keys(row.deps).forEach(function (key) {
                var id = row.deps[key];
                row.indexDeps[key] = index[id];
            });
            if (row.dedupe) {
                row.dedupeIndex = index[row.dedupe];
            }
            tr.push(row);
        });
    }
    else {
        rows.forEach(function (row) { tr.push(row) });
    }
    tr.push(null);
}

function cmp (a, b) {
    return a.id + a.hash < b.id + b.hash ? -1 : 1;
}

function has (obj, key) {
    return Object.prototype.hasOwnProperty.call(obj, key);
}

function depCmp () {
    var deps = {}, hashes = {};
    return { add: add, cmp: cmp }
    
    function add (row, hash) {
        deps[row.id] = row.deps;
        hashes[row.id] = hash;
    }
    function cmp (a, b, limit) {
        if (!a && !b) return true;
        if (!a || !b) return false;
        
        var keys = Object.keys(a);
        if (keys.length !== Object.keys(b).length) return false;

        for (var i = 0; i < keys.length; i++) {
            var k = keys[i], ka = a[k], kb = b[k];
            var ha = hashes[ka];
            var hb = hashes[kb];
            var da = deps[ka];
            var db = deps[kb];

            if (ka === kb) continue;
            if (ha !== hb || (!limit && !cmp(da, db, 1))) {
                return false;
            }
        }
        return true;
    }
}