11cb0ef41Sopenharmony_ciconst debug = require('../internal/debug')
21cb0ef41Sopenharmony_ciconst { MAX_LENGTH, MAX_SAFE_INTEGER } = require('../internal/constants')
31cb0ef41Sopenharmony_ciconst { safeRe: re, t } = require('../internal/re')
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ciconst parseOptions = require('../internal/parse-options')
61cb0ef41Sopenharmony_ciconst { compareIdentifiers } = require('../internal/identifiers')
71cb0ef41Sopenharmony_ciclass SemVer {
81cb0ef41Sopenharmony_ci  constructor (version, options) {
91cb0ef41Sopenharmony_ci    options = parseOptions(options)
101cb0ef41Sopenharmony_ci
111cb0ef41Sopenharmony_ci    if (version instanceof SemVer) {
121cb0ef41Sopenharmony_ci      if (version.loose === !!options.loose &&
131cb0ef41Sopenharmony_ci          version.includePrerelease === !!options.includePrerelease) {
141cb0ef41Sopenharmony_ci        return version
151cb0ef41Sopenharmony_ci      } else {
161cb0ef41Sopenharmony_ci        version = version.version
171cb0ef41Sopenharmony_ci      }
181cb0ef41Sopenharmony_ci    } else if (typeof version !== 'string') {
191cb0ef41Sopenharmony_ci      throw new TypeError(`Invalid version. Must be a string. Got type "${typeof version}".`)
201cb0ef41Sopenharmony_ci    }
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_ci    if (version.length > MAX_LENGTH) {
231cb0ef41Sopenharmony_ci      throw new TypeError(
241cb0ef41Sopenharmony_ci        `version is longer than ${MAX_LENGTH} characters`
251cb0ef41Sopenharmony_ci      )
261cb0ef41Sopenharmony_ci    }
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_ci    debug('SemVer', version, options)
291cb0ef41Sopenharmony_ci    this.options = options
301cb0ef41Sopenharmony_ci    this.loose = !!options.loose
311cb0ef41Sopenharmony_ci    // this isn't actually relevant for versions, but keep it so that we
321cb0ef41Sopenharmony_ci    // don't run into trouble passing this.options around.
331cb0ef41Sopenharmony_ci    this.includePrerelease = !!options.includePrerelease
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_ci    const m = version.trim().match(options.loose ? re[t.LOOSE] : re[t.FULL])
361cb0ef41Sopenharmony_ci
371cb0ef41Sopenharmony_ci    if (!m) {
381cb0ef41Sopenharmony_ci      throw new TypeError(`Invalid Version: ${version}`)
391cb0ef41Sopenharmony_ci    }
401cb0ef41Sopenharmony_ci
411cb0ef41Sopenharmony_ci    this.raw = version
421cb0ef41Sopenharmony_ci
431cb0ef41Sopenharmony_ci    // these are actually numbers
441cb0ef41Sopenharmony_ci    this.major = +m[1]
451cb0ef41Sopenharmony_ci    this.minor = +m[2]
461cb0ef41Sopenharmony_ci    this.patch = +m[3]
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_ci    if (this.major > MAX_SAFE_INTEGER || this.major < 0) {
491cb0ef41Sopenharmony_ci      throw new TypeError('Invalid major version')
501cb0ef41Sopenharmony_ci    }
511cb0ef41Sopenharmony_ci
521cb0ef41Sopenharmony_ci    if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) {
531cb0ef41Sopenharmony_ci      throw new TypeError('Invalid minor version')
541cb0ef41Sopenharmony_ci    }
551cb0ef41Sopenharmony_ci
561cb0ef41Sopenharmony_ci    if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) {
571cb0ef41Sopenharmony_ci      throw new TypeError('Invalid patch version')
581cb0ef41Sopenharmony_ci    }
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_ci    // numberify any prerelease numeric ids
611cb0ef41Sopenharmony_ci    if (!m[4]) {
621cb0ef41Sopenharmony_ci      this.prerelease = []
631cb0ef41Sopenharmony_ci    } else {
641cb0ef41Sopenharmony_ci      this.prerelease = m[4].split('.').map((id) => {
651cb0ef41Sopenharmony_ci        if (/^[0-9]+$/.test(id)) {
661cb0ef41Sopenharmony_ci          const num = +id
671cb0ef41Sopenharmony_ci          if (num >= 0 && num < MAX_SAFE_INTEGER) {
681cb0ef41Sopenharmony_ci            return num
691cb0ef41Sopenharmony_ci          }
701cb0ef41Sopenharmony_ci        }
711cb0ef41Sopenharmony_ci        return id
721cb0ef41Sopenharmony_ci      })
731cb0ef41Sopenharmony_ci    }
741cb0ef41Sopenharmony_ci
751cb0ef41Sopenharmony_ci    this.build = m[5] ? m[5].split('.') : []
761cb0ef41Sopenharmony_ci    this.format()
771cb0ef41Sopenharmony_ci  }
781cb0ef41Sopenharmony_ci
791cb0ef41Sopenharmony_ci  format () {
801cb0ef41Sopenharmony_ci    this.version = `${this.major}.${this.minor}.${this.patch}`
811cb0ef41Sopenharmony_ci    if (this.prerelease.length) {
821cb0ef41Sopenharmony_ci      this.version += `-${this.prerelease.join('.')}`
831cb0ef41Sopenharmony_ci    }
841cb0ef41Sopenharmony_ci    return this.version
851cb0ef41Sopenharmony_ci  }
861cb0ef41Sopenharmony_ci
871cb0ef41Sopenharmony_ci  toString () {
881cb0ef41Sopenharmony_ci    return this.version
891cb0ef41Sopenharmony_ci  }
901cb0ef41Sopenharmony_ci
911cb0ef41Sopenharmony_ci  compare (other) {
921cb0ef41Sopenharmony_ci    debug('SemVer.compare', this.version, this.options, other)
931cb0ef41Sopenharmony_ci    if (!(other instanceof SemVer)) {
941cb0ef41Sopenharmony_ci      if (typeof other === 'string' && other === this.version) {
951cb0ef41Sopenharmony_ci        return 0
961cb0ef41Sopenharmony_ci      }
971cb0ef41Sopenharmony_ci      other = new SemVer(other, this.options)
981cb0ef41Sopenharmony_ci    }
991cb0ef41Sopenharmony_ci
1001cb0ef41Sopenharmony_ci    if (other.version === this.version) {
1011cb0ef41Sopenharmony_ci      return 0
1021cb0ef41Sopenharmony_ci    }
1031cb0ef41Sopenharmony_ci
1041cb0ef41Sopenharmony_ci    return this.compareMain(other) || this.comparePre(other)
1051cb0ef41Sopenharmony_ci  }
1061cb0ef41Sopenharmony_ci
1071cb0ef41Sopenharmony_ci  compareMain (other) {
1081cb0ef41Sopenharmony_ci    if (!(other instanceof SemVer)) {
1091cb0ef41Sopenharmony_ci      other = new SemVer(other, this.options)
1101cb0ef41Sopenharmony_ci    }
1111cb0ef41Sopenharmony_ci
1121cb0ef41Sopenharmony_ci    return (
1131cb0ef41Sopenharmony_ci      compareIdentifiers(this.major, other.major) ||
1141cb0ef41Sopenharmony_ci      compareIdentifiers(this.minor, other.minor) ||
1151cb0ef41Sopenharmony_ci      compareIdentifiers(this.patch, other.patch)
1161cb0ef41Sopenharmony_ci    )
1171cb0ef41Sopenharmony_ci  }
1181cb0ef41Sopenharmony_ci
1191cb0ef41Sopenharmony_ci  comparePre (other) {
1201cb0ef41Sopenharmony_ci    if (!(other instanceof SemVer)) {
1211cb0ef41Sopenharmony_ci      other = new SemVer(other, this.options)
1221cb0ef41Sopenharmony_ci    }
1231cb0ef41Sopenharmony_ci
1241cb0ef41Sopenharmony_ci    // NOT having a prerelease is > having one
1251cb0ef41Sopenharmony_ci    if (this.prerelease.length && !other.prerelease.length) {
1261cb0ef41Sopenharmony_ci      return -1
1271cb0ef41Sopenharmony_ci    } else if (!this.prerelease.length && other.prerelease.length) {
1281cb0ef41Sopenharmony_ci      return 1
1291cb0ef41Sopenharmony_ci    } else if (!this.prerelease.length && !other.prerelease.length) {
1301cb0ef41Sopenharmony_ci      return 0
1311cb0ef41Sopenharmony_ci    }
1321cb0ef41Sopenharmony_ci
1331cb0ef41Sopenharmony_ci    let i = 0
1341cb0ef41Sopenharmony_ci    do {
1351cb0ef41Sopenharmony_ci      const a = this.prerelease[i]
1361cb0ef41Sopenharmony_ci      const b = other.prerelease[i]
1371cb0ef41Sopenharmony_ci      debug('prerelease compare', i, a, b)
1381cb0ef41Sopenharmony_ci      if (a === undefined && b === undefined) {
1391cb0ef41Sopenharmony_ci        return 0
1401cb0ef41Sopenharmony_ci      } else if (b === undefined) {
1411cb0ef41Sopenharmony_ci        return 1
1421cb0ef41Sopenharmony_ci      } else if (a === undefined) {
1431cb0ef41Sopenharmony_ci        return -1
1441cb0ef41Sopenharmony_ci      } else if (a === b) {
1451cb0ef41Sopenharmony_ci        continue
1461cb0ef41Sopenharmony_ci      } else {
1471cb0ef41Sopenharmony_ci        return compareIdentifiers(a, b)
1481cb0ef41Sopenharmony_ci      }
1491cb0ef41Sopenharmony_ci    } while (++i)
1501cb0ef41Sopenharmony_ci  }
1511cb0ef41Sopenharmony_ci
1521cb0ef41Sopenharmony_ci  compareBuild (other) {
1531cb0ef41Sopenharmony_ci    if (!(other instanceof SemVer)) {
1541cb0ef41Sopenharmony_ci      other = new SemVer(other, this.options)
1551cb0ef41Sopenharmony_ci    }
1561cb0ef41Sopenharmony_ci
1571cb0ef41Sopenharmony_ci    let i = 0
1581cb0ef41Sopenharmony_ci    do {
1591cb0ef41Sopenharmony_ci      const a = this.build[i]
1601cb0ef41Sopenharmony_ci      const b = other.build[i]
1611cb0ef41Sopenharmony_ci      debug('prerelease compare', i, a, b)
1621cb0ef41Sopenharmony_ci      if (a === undefined && b === undefined) {
1631cb0ef41Sopenharmony_ci        return 0
1641cb0ef41Sopenharmony_ci      } else if (b === undefined) {
1651cb0ef41Sopenharmony_ci        return 1
1661cb0ef41Sopenharmony_ci      } else if (a === undefined) {
1671cb0ef41Sopenharmony_ci        return -1
1681cb0ef41Sopenharmony_ci      } else if (a === b) {
1691cb0ef41Sopenharmony_ci        continue
1701cb0ef41Sopenharmony_ci      } else {
1711cb0ef41Sopenharmony_ci        return compareIdentifiers(a, b)
1721cb0ef41Sopenharmony_ci      }
1731cb0ef41Sopenharmony_ci    } while (++i)
1741cb0ef41Sopenharmony_ci  }
1751cb0ef41Sopenharmony_ci
1761cb0ef41Sopenharmony_ci  // preminor will bump the version up to the next minor release, and immediately
1771cb0ef41Sopenharmony_ci  // down to pre-release. premajor and prepatch work the same way.
1781cb0ef41Sopenharmony_ci  inc (release, identifier, identifierBase) {
1791cb0ef41Sopenharmony_ci    switch (release) {
1801cb0ef41Sopenharmony_ci      case 'premajor':
1811cb0ef41Sopenharmony_ci        this.prerelease.length = 0
1821cb0ef41Sopenharmony_ci        this.patch = 0
1831cb0ef41Sopenharmony_ci        this.minor = 0
1841cb0ef41Sopenharmony_ci        this.major++
1851cb0ef41Sopenharmony_ci        this.inc('pre', identifier, identifierBase)
1861cb0ef41Sopenharmony_ci        break
1871cb0ef41Sopenharmony_ci      case 'preminor':
1881cb0ef41Sopenharmony_ci        this.prerelease.length = 0
1891cb0ef41Sopenharmony_ci        this.patch = 0
1901cb0ef41Sopenharmony_ci        this.minor++
1911cb0ef41Sopenharmony_ci        this.inc('pre', identifier, identifierBase)
1921cb0ef41Sopenharmony_ci        break
1931cb0ef41Sopenharmony_ci      case 'prepatch':
1941cb0ef41Sopenharmony_ci        // If this is already a prerelease, it will bump to the next version
1951cb0ef41Sopenharmony_ci        // drop any prereleases that might already exist, since they are not
1961cb0ef41Sopenharmony_ci        // relevant at this point.
1971cb0ef41Sopenharmony_ci        this.prerelease.length = 0
1981cb0ef41Sopenharmony_ci        this.inc('patch', identifier, identifierBase)
1991cb0ef41Sopenharmony_ci        this.inc('pre', identifier, identifierBase)
2001cb0ef41Sopenharmony_ci        break
2011cb0ef41Sopenharmony_ci      // If the input is a non-prerelease version, this acts the same as
2021cb0ef41Sopenharmony_ci      // prepatch.
2031cb0ef41Sopenharmony_ci      case 'prerelease':
2041cb0ef41Sopenharmony_ci        if (this.prerelease.length === 0) {
2051cb0ef41Sopenharmony_ci          this.inc('patch', identifier, identifierBase)
2061cb0ef41Sopenharmony_ci        }
2071cb0ef41Sopenharmony_ci        this.inc('pre', identifier, identifierBase)
2081cb0ef41Sopenharmony_ci        break
2091cb0ef41Sopenharmony_ci
2101cb0ef41Sopenharmony_ci      case 'major':
2111cb0ef41Sopenharmony_ci        // If this is a pre-major version, bump up to the same major version.
2121cb0ef41Sopenharmony_ci        // Otherwise increment major.
2131cb0ef41Sopenharmony_ci        // 1.0.0-5 bumps to 1.0.0
2141cb0ef41Sopenharmony_ci        // 1.1.0 bumps to 2.0.0
2151cb0ef41Sopenharmony_ci        if (
2161cb0ef41Sopenharmony_ci          this.minor !== 0 ||
2171cb0ef41Sopenharmony_ci          this.patch !== 0 ||
2181cb0ef41Sopenharmony_ci          this.prerelease.length === 0
2191cb0ef41Sopenharmony_ci        ) {
2201cb0ef41Sopenharmony_ci          this.major++
2211cb0ef41Sopenharmony_ci        }
2221cb0ef41Sopenharmony_ci        this.minor = 0
2231cb0ef41Sopenharmony_ci        this.patch = 0
2241cb0ef41Sopenharmony_ci        this.prerelease = []
2251cb0ef41Sopenharmony_ci        break
2261cb0ef41Sopenharmony_ci      case 'minor':
2271cb0ef41Sopenharmony_ci        // If this is a pre-minor version, bump up to the same minor version.
2281cb0ef41Sopenharmony_ci        // Otherwise increment minor.
2291cb0ef41Sopenharmony_ci        // 1.2.0-5 bumps to 1.2.0
2301cb0ef41Sopenharmony_ci        // 1.2.1 bumps to 1.3.0
2311cb0ef41Sopenharmony_ci        if (this.patch !== 0 || this.prerelease.length === 0) {
2321cb0ef41Sopenharmony_ci          this.minor++
2331cb0ef41Sopenharmony_ci        }
2341cb0ef41Sopenharmony_ci        this.patch = 0
2351cb0ef41Sopenharmony_ci        this.prerelease = []
2361cb0ef41Sopenharmony_ci        break
2371cb0ef41Sopenharmony_ci      case 'patch':
2381cb0ef41Sopenharmony_ci        // If this is not a pre-release version, it will increment the patch.
2391cb0ef41Sopenharmony_ci        // If it is a pre-release it will bump up to the same patch version.
2401cb0ef41Sopenharmony_ci        // 1.2.0-5 patches to 1.2.0
2411cb0ef41Sopenharmony_ci        // 1.2.0 patches to 1.2.1
2421cb0ef41Sopenharmony_ci        if (this.prerelease.length === 0) {
2431cb0ef41Sopenharmony_ci          this.patch++
2441cb0ef41Sopenharmony_ci        }
2451cb0ef41Sopenharmony_ci        this.prerelease = []
2461cb0ef41Sopenharmony_ci        break
2471cb0ef41Sopenharmony_ci      // This probably shouldn't be used publicly.
2481cb0ef41Sopenharmony_ci      // 1.0.0 'pre' would become 1.0.0-0 which is the wrong direction.
2491cb0ef41Sopenharmony_ci      case 'pre': {
2501cb0ef41Sopenharmony_ci        const base = Number(identifierBase) ? 1 : 0
2511cb0ef41Sopenharmony_ci
2521cb0ef41Sopenharmony_ci        if (!identifier && identifierBase === false) {
2531cb0ef41Sopenharmony_ci          throw new Error('invalid increment argument: identifier is empty')
2541cb0ef41Sopenharmony_ci        }
2551cb0ef41Sopenharmony_ci
2561cb0ef41Sopenharmony_ci        if (this.prerelease.length === 0) {
2571cb0ef41Sopenharmony_ci          this.prerelease = [base]
2581cb0ef41Sopenharmony_ci        } else {
2591cb0ef41Sopenharmony_ci          let i = this.prerelease.length
2601cb0ef41Sopenharmony_ci          while (--i >= 0) {
2611cb0ef41Sopenharmony_ci            if (typeof this.prerelease[i] === 'number') {
2621cb0ef41Sopenharmony_ci              this.prerelease[i]++
2631cb0ef41Sopenharmony_ci              i = -2
2641cb0ef41Sopenharmony_ci            }
2651cb0ef41Sopenharmony_ci          }
2661cb0ef41Sopenharmony_ci          if (i === -1) {
2671cb0ef41Sopenharmony_ci            // didn't increment anything
2681cb0ef41Sopenharmony_ci            if (identifier === this.prerelease.join('.') && identifierBase === false) {
2691cb0ef41Sopenharmony_ci              throw new Error('invalid increment argument: identifier already exists')
2701cb0ef41Sopenharmony_ci            }
2711cb0ef41Sopenharmony_ci            this.prerelease.push(base)
2721cb0ef41Sopenharmony_ci          }
2731cb0ef41Sopenharmony_ci        }
2741cb0ef41Sopenharmony_ci        if (identifier) {
2751cb0ef41Sopenharmony_ci          // 1.2.0-beta.1 bumps to 1.2.0-beta.2,
2761cb0ef41Sopenharmony_ci          // 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0
2771cb0ef41Sopenharmony_ci          let prerelease = [identifier, base]
2781cb0ef41Sopenharmony_ci          if (identifierBase === false) {
2791cb0ef41Sopenharmony_ci            prerelease = [identifier]
2801cb0ef41Sopenharmony_ci          }
2811cb0ef41Sopenharmony_ci          if (compareIdentifiers(this.prerelease[0], identifier) === 0) {
2821cb0ef41Sopenharmony_ci            if (isNaN(this.prerelease[1])) {
2831cb0ef41Sopenharmony_ci              this.prerelease = prerelease
2841cb0ef41Sopenharmony_ci            }
2851cb0ef41Sopenharmony_ci          } else {
2861cb0ef41Sopenharmony_ci            this.prerelease = prerelease
2871cb0ef41Sopenharmony_ci          }
2881cb0ef41Sopenharmony_ci        }
2891cb0ef41Sopenharmony_ci        break
2901cb0ef41Sopenharmony_ci      }
2911cb0ef41Sopenharmony_ci      default:
2921cb0ef41Sopenharmony_ci        throw new Error(`invalid increment argument: ${release}`)
2931cb0ef41Sopenharmony_ci    }
2941cb0ef41Sopenharmony_ci    this.raw = this.format()
2951cb0ef41Sopenharmony_ci    if (this.build.length) {
2961cb0ef41Sopenharmony_ci      this.raw += `+${this.build.join('.')}`
2971cb0ef41Sopenharmony_ci    }
2981cb0ef41Sopenharmony_ci    return this
2991cb0ef41Sopenharmony_ci  }
3001cb0ef41Sopenharmony_ci}
3011cb0ef41Sopenharmony_ci
3021cb0ef41Sopenharmony_cimodule.exports = SemVer
303