codekingpro/portable-devtools
115k
1const EE = require('events')
2const onProgress = Symbol('onProgress')
3const bars = Symbol('bars')
4const listener = Symbol('listener')
5const normData = Symbol('normData')
6class Client extends EE {
7 constructor ({ normalize = false, stopOnDone = false } = {}) {
8 super()
9 this.normalize = !!normalize
10 this.stopOnDone = !!stopOnDone
11 this[bars] = new Map()
12 this[listener] = null
13 }
14
15 get size () {
16 return this[bars].size
17 }
18
19 get listening () {
20 return !!this[listener]
21 }
22
23 addListener (...args) {
24 return this.on(...args)
25 }
26
27 on (ev, ...args) {
28 if (ev === 'progress' && !this[listener]) {
29 this.start()
30 }
31 return super.on(ev, ...args)
32 }
33
34 off (ev, ...args) {
35 return this.removeListener(ev, ...args)
36 }
37
38 removeListener (ev, ...args) {
39 const ret = super.removeListener(ev, ...args)
40 if (ev === 'progress' && this.listeners(ev).length === 0) {
41 this.stop()
42 }
43 return ret
44 }
45
46 stop () {
47 if (this[listener]) {
48 process.removeListener('progress', this[listener])
49 this[listener] = null
50 }
51 }
52
53 start () {
54 if (!this[listener]) {
55 this[listener] = (...args) => this[onProgress](...args)
56 process.on('progress', this[listener])
57 }
58 }
59
60 [onProgress] (key, data) {
61 data = this[normData](key, data)
62 if (!this[bars].has(key)) {
63 this.emit('bar', key, data)
64 }
65 this[bars].set(key, data)
66 this.emit('progress', key, data)
67 if (data.done) {
68 this[bars].delete(key)
69 this.emit('barDone', key, data)
70 if (this.size === 0) {
71 if (this.stopOnDone) {
72 this.stop()
73 }
74 this.emit('done')
75 }
76 }
77 }
78
79 [normData] (key, data) {
80 const actualValue = data.value
81 const actualTotal = data.total
82 let value = actualValue
83 let total = actualTotal
84 const done = data.done || value >= total
85 if (this.normalize) {
86 const bar = this[bars].get(key)
87 total = 100
88 if (done) {
89 value = 100
90 } else {
91 // show value as a portion of 100
92 const pct = 100 * actualValue / actualTotal
93 if (bar) {
94 // don't ever go backwards, and don't stand still
95 // move at least 1% of the remaining value if it wouldn't move.
96 value = (pct > bar.value) ? pct
97 : (100 - bar.value) / 100 + bar.value
98 }
99 }
100 }
101 // include the key
102 return {
103 ...data,
104 key,
105 name: data.name || key,
106 value,
107 total,
108 actualValue,
109 actualTotal,
110 done,
111 }
112 }
113}
114module.exports = Client
115 