Version constraint challenge

by Arnaud Buchholz

HTML

<script src="https://arnaudbuchholz.github.io/blog/jsfiddle-assert.js"></script>

JavaScript

const split = version => {
  let [,
    major,
    minor,
    patch,
    snapshot
  ] = version.match(/(\d+)\.(\d+)(?:\.(\d+)(-SNAPSHOT)?)?/i)
  return [Number(major), Number(minor), Number(patch || '0'), snapshot ? 1 : 0]
}

assert(() => split('1.0').join('.') === '1.0.0.0')
assert(() => split('1.53.6').join('.') === '1.53.6.0')
assert(() => split('1.53.6-snapshot').join('.') === '1.53.6.1')

const compare = (version1, version2) => {
  const [major1, minor1, patch1, snapshot1] = split(version1)
  const [major2, minor2, patch2, snapshot2] = split(version2)
  if (major1 !== major2) {
    return major1 - major2
  }
  if (minor1 !== minor2) {
    return minor1 - minor2
  }
  if (patch1 !== patch2) {
    return patch1 - patch2
  }
  return snapshot1 - snapshot2
}

const isLower = (version1, version2) => compare(version1, version2) < 0

assert(() => isLower('0.0.1', '1.0'))
assert(() => !isLower('1.0', '0.0.1'))
assert(() => isLower('1.5', '2.2'))
assert(() => !isLower('1.5', '1.2'))
assert(() => isLower('1.0', '1.2'))
assert(() => !isLower('1.2', '1.0'))
assert(() => isLower('1.2.5', '1.2.6'))
assert(() => isLower('1.2.6', '1.2.6-snapshot'))

const isLowerOrEqual = (version1, version2) => compare(version1, version2) <= 0

assert(() => isLowerOrEqual('0.0.1', '1.0'))
assert(() => !isLowerOrEqual('1.0', '0.0.1'))
assert(() => isLowerOrEqual('1.5', '1.5.0'))
assert(() => isLowerOrEqual('1.5', '2.2'))
assert(() => isLowerOrEqual('1.0', '1.2'))
assert(() => !isLowerOrEqual('1.2', '1.0'))
assert(() => isLowerOrEqual('1.2.5', '1.2.6'))
assert(() => isLowerOrEqual('1.2.6', '1.2.6-snapshot'))
assert(() => ['2.5', '0.0.1', '1.2', '1.0.2'].sort(compare).join(',') === '0.0.1,1.0.2,1.2,2.5')

const buildFilter = constraint => {
  const [,
    minIncluded,
    minVersion,
    maxVersion,
    maxIncluded
  ] = constraint.match(/(\[|\()([^,]*),([^\])]*)(\]|\))/)
  
  let checkMin
  if (minIncluded === '[') {
    checkMin = version => isLowerOrEqual(minVersion, version)
  } else {
  ...