Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes15kdownloads
semver.js334 linesDownload Raw Back to classes
1'use strict'
2
3const debug = require('../internal/debug')
4const { MAX_LENGTH, MAX_SAFE_INTEGER } = require('../internal/constants')
5const { safeRe: re, t } = require('../internal/re')
6
7const parseOptions = require('../internal/parse-options')
8const { compareIdentifiers } = require('../internal/identifiers')
9class SemVer {
10  constructor (version, options) {
11    options = parseOptions(options)
12
13    if (version instanceof SemVer) {
14      if (version.loose === !!options.loose &&
15        version.includePrerelease === !!options.includePrerelease) {
16        return version
17      } else {
18        version = version.version
19      }
20    } else if (typeof version !== 'string') {
21      throw new TypeError(`Invalid version. Must be a string. Got type "${typeof version}".`)
22    }
23
24    if (version.length > MAX_LENGTH) {
25      throw new TypeError(
26        `version is longer than ${MAX_LENGTH} characters`
27      )
28    }
29
30    debug('SemVer', version, options)
31    this.options = options
32    this.loose = !!options.loose
33    // this isn't actually relevant for versions, but keep it so that we
34    // don't run into trouble passing this.options around.
35    this.includePrerelease = !!options.includePrerelease
36
37    const m = version.trim().match(options.loose ? re[t.LOOSE] : re[t.FULL])
38
39    if (!m) {
40      throw new TypeError(`Invalid Version: ${version}`)
41    }
42
43    this.raw = version
44
45    // these are actually numbers
46    this.major = +m[1]
47    this.minor = +m[2]
48    this.patch = +m[3]
49
50    if (this.major > MAX_SAFE_INTEGER || this.major < 0) {
51      throw new TypeError('Invalid major version')
52    }
53
54    if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) {
55      throw new TypeError('Invalid minor version')
56    }
57
58    if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) {
59      throw new TypeError('Invalid patch version')
60    }
61
62    // numberify any prerelease numeric ids
63    if (!m[4]) {
64      this.prerelease = []
65    } else {
66      this.prerelease = m[4].split('.').map((id) => {
67        if (/^[0-9]+$/.test(id)) {
68          const num = +id
69          if (num >= 0 && num < MAX_SAFE_INTEGER) {
70            return num
71          }
72        }
73        return id
74      })
75    }
76
77    this.build = m[5] ? m[5].split('.') : []
78    this.format()
79  }
80
81  format () {
82    this.version = `${this.major}.${this.minor}.${this.patch}`
83    if (this.prerelease.length) {
84      this.version += `-${this.prerelease.join('.')}`
85    }
86    return this.version
87  }
88
89  toString () {
90    return this.version
91  }
92
93  compare (other) {
94    debug('SemVer.compare', this.version, this.options, other)
95    if (!(other instanceof SemVer)) {
96      if (typeof other === 'string' && other === this.version) {
97        return 0
98      }
99      other = new SemVer(other, this.options)
100    }
101
102    if (other.version === this.version) {
103      return 0
104    }
105
106    return this.compareMain(other) || this.comparePre(other)
107  }
108
109  compareMain (other) {
110    if (!(other instanceof SemVer)) {
111      other = new SemVer(other, this.options)
112    }
113
114    if (this.major < other.major) {
115      return -1
116    }
117    if (this.major > other.major) {
118      return 1
119    }
120    if (this.minor < other.minor) {
121      return -1
122    }
123    if (this.minor > other.minor) {
124      return 1
125    }
126    if (this.patch < other.patch) {
127      return -1
128    }
129    if (this.patch > other.patch) {
130      return 1
131    }
132    return 0
133  }
134
135  comparePre (other) {
136    if (!(other instanceof SemVer)) {
137      other = new SemVer(other, this.options)
138    }
139
140    // NOT having a prerelease is > having one
141    if (this.prerelease.length && !other.prerelease.length) {
142      return -1
143    } else if (!this.prerelease.length && other.prerelease.length) {
144      return 1
145    } else if (!this.prerelease.length && !other.prerelease.length) {
146      return 0
147    }
148
149    let i = 0
150    do {
151      const a = this.prerelease[i]
152      const b = other.prerelease[i]
153      debug('prerelease compare', i, a, b)
154      if (a === undefined && b === undefined) {
155        return 0
156      } else if (b === undefined) {
157        return 1
158      } else if (a === undefined) {
159        return -1
160      } else if (a === b) {
161        continue
162      } else {
163        return compareIdentifiers(a, b)
164      }
165    } while (++i)
166  }
167
168  compareBuild (other) {
169    if (!(other instanceof SemVer)) {
170      other = new SemVer(other, this.options)
171    }
172
173    let i = 0
174    do {
175      const a = this.build[i]
176      const b = other.build[i]
177      debug('build compare', i, a, b)
178      if (a === undefined && b === undefined) {
179        return 0
180      } else if (b === undefined) {
181        return 1
182      } else if (a === undefined) {
183        return -1
184      } else if (a === b) {
185        continue
186      } else {
187        return compareIdentifiers(a, b)
188      }
189    } while (++i)
190  }
191
192  // preminor will bump the version up to the next minor release, and immediately
193  // down to pre-release. premajor and prepatch work the same way.
194  inc (release, identifier, identifierBase) {
195    if (release.startsWith('pre')) {
196      if (!identifier && identifierBase === false) {
197        throw new Error('invalid increment argument: identifier is empty')
198      }
199      // Avoid an invalid semver results
200      if (identifier) {
201        const match = `-${identifier}`.match(this.options.loose ? re[t.PRERELEASELOOSE] : re[t.PRERELEASE])
202        if (!match || match[1] !== identifier) {
203          throw new Error(`invalid identifier: ${identifier}`)
204        }
205      }
206    }
207
208    switch (release) {
209      case 'premajor':
210        this.prerelease.length = 0
211        this.patch = 0
212        this.minor = 0
213        this.major++
214        this.inc('pre', identifier, identifierBase)
215        break
216      case 'preminor':
217        this.prerelease.length = 0
218        this.patch = 0
219        this.minor++
220        this.inc('pre', identifier, identifierBase)
221        break
222      case 'prepatch':
223        // If this is already a prerelease, it will bump to the next version
224        // drop any prereleases that might already exist, since they are not
225        // relevant at this point.
226        this.prerelease.length = 0
227        this.inc('patch', identifier, identifierBase)
228        this.inc('pre', identifier, identifierBase)
229        break
230      // If the input is a non-prerelease version, this acts the same as
231      // prepatch.
232      case 'prerelease':
233        if (this.prerelease.length === 0) {
234          this.inc('patch', identifier, identifierBase)
235        }
236        this.inc('pre', identifier, identifierBase)
237        break
238      case 'release':
239        if (this.prerelease.length === 0) {
240          throw new Error(`version ${this.raw} is not a prerelease`)
241        }
242        this.prerelease.length = 0
243        break
244
245      case 'major':
246        // If this is a pre-major version, bump up to the same major version.
247        // Otherwise increment major.
248        // 1.0.0-5 bumps to 1.0.0
249        // 1.1.0 bumps to 2.0.0
250        if (
251          this.minor !== 0 ||
252          this.patch !== 0 ||
253          this.prerelease.length === 0
254        ) {
255          this.major++
256        }
257        this.minor = 0
258        this.patch = 0
259        this.prerelease = []
260        break
261      case 'minor':
262        // If this is a pre-minor version, bump up to the same minor version.
263        // Otherwise increment minor.
264        // 1.2.0-5 bumps to 1.2.0
265        // 1.2.1 bumps to 1.3.0
266        if (this.patch !== 0 || this.prerelease.length === 0) {
267          this.minor++
268        }
269        this.patch = 0
270        this.prerelease = []
271        break
272      case 'patch':
273        // If this is not a pre-release version, it will increment the patch.
274        // If it is a pre-release it will bump up to the same patch version.
275        // 1.2.0-5 patches to 1.2.0
276        // 1.2.0 patches to 1.2.1
277        if (this.prerelease.length === 0) {
278          this.patch++
279        }
280        this.prerelease = []
281        break
282      // This probably shouldn't be used publicly.
283      // 1.0.0 'pre' would become 1.0.0-0 which is the wrong direction.
284      case 'pre': {
285        const base = Number(identifierBase) ? 1 : 0
286
287        if (this.prerelease.length === 0) {
288          this.prerelease = [base]
289        } else {
290          let i = this.prerelease.length
291          while (--i >= 0) {
292            if (typeof this.prerelease[i] === 'number') {
293              this.prerelease[i]++
294              i = -2
295            }
296          }
297          if (i === -1) {
298            // didn't increment anything
299            if (identifier === this.prerelease.join('.') && identifierBase === false) {
300              throw new Error('invalid increment argument: identifier already exists')
301            }
302            this.prerelease.push(base)
303          }
304        }
305        if (identifier) {
306          // 1.2.0-beta.1 bumps to 1.2.0-beta.2,
307          // 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0
308          let prerelease = [identifier, base]
309          if (identifierBase === false) {
310            prerelease = [identifier]
311          }
312          if (compareIdentifiers(this.prerelease[0], identifier) === 0) {
313            if (isNaN(this.prerelease[1])) {
314              this.prerelease = prerelease
315            }
316          } else {
317            this.prerelease = prerelease
318          }
319        }
320        break
321      }
322      default:
323        throw new Error(`invalid increment argument: ${release}`)
324    }
325    this.raw = this.format()
326    if (this.build.length) {
327      this.raw += `+${this.build.join('.')}`
328    }
329    return this
330  }
331}
332
333module.exports = SemVer
334 
codekingpro/portable-devtools · Team Ai