const semVerToNum = (x) =>
  x.match(/(\d+).(\d+).(\d+)/)
   .slice(1)
   .reduce((acc, x, i) => +acc + +x * ([100000, 1000, 1][i]));

const sortSemver = (a, b) => {
  const [a1, b1] = [a, b].map(semVerToNum);
  return a1 === b1
    ? 0 : a1 < b1 ? -1 : 1;
};

const find = (xs, fn) => xs.filter(fn)[0];

const findLatest = (xs) => xs.sort(sortSemver).reverse()[0];

const findPattern = (xs, pattern) => {
  const RX = new RegExp(pattern);
  return findLatest(xs.filter(::RX.test));
};

const resolve = (range, versions, pre) => {
  if (range === 'latest') {
    return findLatest(versions);
  }

  const VERSION_RX = /^([\^\~])?(\d+)\.(\d+)\.(\d+)(-(\w+))?$/;

  let [root, prefix, major, minor] = VERSION_RX.exec(range);

  if (!prefix) {
    return find(versions, (v) => v === root);
  }

  let pattern = prefix === '^'
    ? `^(${ major })\\.(\\d+)\\.(\\d+)`
    : `^(${ major })\.(${ minor })\\.(\\d+)`;

  return pre
    ? findPattern(versions, pattern + '(-(\\w+))?$')
    : findPattern(versions, pattern + '$');
};

const SemVer = { resolve };

export default SemVer;

@@ -64,16 +64,33 @@
 lice(1)%0A
+   .map(m =%3E +m)%0A
    .redu
@@ -111,16 +111,14 @@
  =%3E 
-+
 acc + 
-+
 x * 
@@ -125,16 +125,17 @@
 (%5B100000
+0
 , 1000, 
@@ -140,12 +140,15 @@
 , 1%5D
+)
 %5Bi%5D
-)
+, 0
 );%0A%0A

improve semver sorting precision