UNPKG

4.09 kBPlain TextView Raw
1// external
2import versionClean from 'version-clean'
3import versionCompare from 'version-compare'
4import versionRange from 'version-range'
5
6// local
7import Version, { Status, Row } from './version.js'
8
9/**
10 * A JSON object representing the status of our {@link Versions} instance.
11 * It contains a `success` property, which can be `true` or `false.
12 * It also contains the various version numbers mapped to arrays based on their status.
13 * @example {"success": true, "passed": ["10.6.0", "10.7.0"]}
14 */
15export type JSONResult = {
16 [status in Status]?: Array<string>
17} & {
18 success: boolean
19}
20
21/** Versions */
22export class Versions {
23 /** The list of listeners we will call when updates happen. */
24 listeners: Array<Function> = []
25
26 /** The list of Version instances. */
27 array: Array<Version> = []
28
29 /** Create our Versions instance */
30 constructor(
31 versions: Array<string | number>,
32 listeners: Array<Function> = [],
33 ) {
34 this.listeners.push(...listeners)
35 this.add(versions)
36 }
37
38 /** The comparator to use for sorting an array of versions. */
39 static comparator(left: Version, right: Version): 1 | -1 | 0 {
40 const a = versionClean(left.version)
41 const b = versionClean(right.version)
42 if (!a) {
43 // a was an alias, put it last
44 return 1
45 } else if (!b) {
46 // b was an alias, put it last
47 return -1
48 } else {
49 // otherwise do normal sorting
50 return versionCompare(a, b)
51 }
52 }
53
54 /** Add version(s) to the list. */
55 add(versions: Array<string | number> | string | number) {
56 if (!Array.isArray(versions)) versions = [versions]
57 this.array.push(
58 ...versions.map((v) => {
59 const V = new Version(v, this.listeners)
60 return V
61 }),
62 )
63 this.compact()
64 return this
65 }
66
67 /** Get version(s) from the list. */
68 get(version: string): Version | null {
69 return (
70 this.array.find((V) => V.version === version) ||
71 this.array.find((V) => V.aliases.includes(version)) ||
72 this.array.find((V) => versionRange(V.version, version)) ||
73 null
74 )
75 }
76
77 /** Sort our versions by our comparator. */
78 sort() {
79 this.array.sort(Versions.comparator)
80 return this
81 }
82
83 /** Compact versions that share the same exact version number together. */
84 compact() {
85 const map: { [version: string]: Version } = {}
86 this.array.forEach(function (V) {
87 if (map[V.version]) {
88 map[V.version].alias = V.alias
89 } else {
90 map[V.version] = V
91 }
92 })
93 this.array = Object.values(map)
94 this.sort()
95 return this
96 }
97
98 /** Unless every version of ours was successful, then this will be `false`. */
99 get success() {
100 const failure = this.array.some((V) => V.success === false)
101 return !failure
102 }
103
104 /** Get how many versions we have. */
105 get length() {
106 return this.array.length
107 }
108
109 /** Get the results of our versions as a JSON object. */
110 get json() {
111 const results: JSONResult = { success: true }
112 this.array.forEach(function (V) {
113 results[V.status] = (results[V.status] || []).concat(V.version)
114 if (V.success === false) results.success = false
115 })
116 return results
117 }
118
119 /** An array of {@link Version.row} results for use of displaying our status as a neat table. */
120 get table(): Array<Row> {
121 return this.array.map((V) => V.row)
122 }
123
124 /** An array of the {@link Version.message} results for use of displaying detailed status updates of each version. */
125 get messages(): Array<string> {
126 return this.array.map((V) => V.message)
127 }
128
129 /** Loads each of our versions. */
130 async load(compact = true) {
131 await Promise.all(this.array.map((V) => V.load()))
132 if (compact) {
133 this.compact()
134 } else {
135 this.sort()
136 }
137 return this
138 }
139
140 /** Installs any missing versions. */
141 async install() {
142 await Promise.all(this.array.map((V) => V.install()))
143 return this
144 }
145
146 /** Runs the test for each version. */
147 async test(command: string, serial: boolean = false) {
148 if (!command) {
149 throw new Error('no command provided to the testen versions runner')
150 }
151 if (serial) {
152 for (const V of this.array) {
153 await V.test(command)
154 }
155 } else {
156 await Promise.all(this.array.map((V) => V.test(command)))
157 }
158 return this
159 }
160}
161export default Versions