{"size": 2195, "ext": "js", "max_stars_repo_path": "tasks/set-npm-canary-version.js", "max_stars_repo_name": "maks-rafalko/stryker-dashboard", "max_stars_repo_stars_event_min_datetime": "2018-02-09T13:02:25.000Z", "max_stars_repo_stars_event_max_datetime": "2021-12-27T19:58:44.000Z", "max_issues_repo_path": "tasks/set-npm-canary-version.js", "max_issues_repo_name": "maks-rafalko/stryker-dashboard", "max_issues_repo_issues_event_min_datetime": "2018-02-09T05:40:43.000Z", "max_issues_repo_issues_event_max_datetime": "2022-03-02T01:28:08.000Z", "max_forks_repo_path": "tasks/set-npm-canary-version.js", "max_forks_repo_name": "maks-rafalko/stryker-dashboard", "max_forks_repo_forks_event_min_datetime": "2019-08-02T07:56:46.000Z", "max_forks_repo_forks_event_max_datetime": "2021-12-27T19:03:18.000Z"}
{"max_stars_count": 13, "max_issues_count": 138, "max_forks_count": 11, "avg_line_length": 30.0684931507, "max_line_length": 135, "alphanum_fraction": 0.7029612756}
// @ts-check

/**
 * This file will determine the next canary version number, setting it in the NPM_PACKAGE_VERSION variable for all next actions to use.
 * Instead of Lerna's algorithm, it validates that the next version does not yet exist.
 * Unfortunately Lerna itself doesn't support this
 */
const core = require('@actions/core');
const axios = require('axios').default;
const semver = require('semver');
const describeRef = require('@lerna/describe-ref');


determineNextCanaryVersion().catch(err => {
  console.error(err);
  process.exitCode = 1;
});

async function determineNextCanaryVersion() {
  const ref = determineRef();
  const preId = sanitize(ref);
  const nextPatchVersion = await describeNextPatchVersion();
  const { versions } = (await axios('https://registry.npmjs.org/@stryker-mutator/dashboard-backend')).data;
  const revision = determineNextFreeRevision(nextPatchVersion, preId, versions);
  const npmVersion = formatVersion(nextPatchVersion, preId, revision);
  core.exportVariable('NPM_PACKAGE_VERSION', npmVersion);
  console.log(npmVersion);
}

/**
 * @param {string} version 
 * @param {string} preId 
 * @param {number} revision
 */
function formatVersion(version, preId, revision) {
    return `${version}-${preId}.${revision}`;
  }

async function describeNextPatchVersion() {
  const { lastVersion } = await describeRef();
  return semver.inc(lastVersion, 'patch');
}

/**
 * @param {string} ref 
 */
function sanitize(ref) {
  // Sanitizes a github ref name to be a valid pre-id according to semver spec: https://semver.org/#spec-item-9
  return ref.replace(/\//g, '-');
}

function determineRef() {
  const rawRef = process.env.GITHUB_REF;
  if(!rawRef){
    throw new Error('Env variable GITHUB_REF was not set!');
  }
  // rawRef will be in the form "refs/pull/:prNumber/merge" or "refs/heads/feat/branch-1"
  const [, type, ...name] = rawRef.split('/');
  if (type === 'pull') {
    return `pr-${name[0]}`
  } else {
    return name.join('/');
  }
}

function determineNextFreeRevision(version, preId, existingVersions) {
  let revision = 0;
  while (formatVersion(version, preId, revision) in existingVersions) {
    revision++;
  }
  return revision;
}
