<commit_before>const { exec } = require('sb-exec');
const semver = require('semver');

// Flags
// Enable debug output
const DEBUG = false;
// Include development packages when checking whether a peerDependency has been
// satisfied.
const INCLUDE_DEV = true;
// Use the local package.json files or check NPM to determine the peerDependencies
const USE_LOCAL_PEERDEPS = true;

// Internal vars
const deps = new Map();
const npmVers = new Map();
const peerDeps = new Map();

const log = (value) => {
  if (DEBUG) {
    console.log(value);
  }
};

const addDeps = (dependencies) => {
  Object.entries(dependencies).forEach((entry) => {
    const [name, range] = entry;
    deps.set(name, range);
  });
};

const gatherNpmVer = async (range, name) => {
  log(`Getting versions for ${name}@${range}...`);
  const opts = ['view', '--json', name, 'versions'];
  const versions = JSON.parse(await exec('npm', opts));
  const ranges = {
    versions,
    minimum: semver.minSatisfying(versions, range),
    maximum: semver.maxSatisfying(versions, range),
  };
  log(`${name}@${range}: '${ranges.minimum}' to '${ranges.maximum}'`);
  npmVers.set(name, ranges);
};

const getNpmVersions = async () => {
  // Gather the unique package names
  const toCheck = new Set();
  peerDeps.forEach((peerDependencies) => {
    peerDependencies.forEach((range, name) => {
      toCheck.add(name);
    });
  });

  // Grab the versions from NPM
  return Promise.all(Array.from(toCheck.values()).map(async (name) => {
    if (deps.has(name)) {
      await gatherNpmVer(deps.get(name), name);
    }
  }));
};

// Get the peerDependencies
const getNpmPeerDep = async (range, name) => {
  log(`Getting peerDependencies for ${name}`);
  const opts = ['view', '--json', name, 'peerDependencies'];
  const npmPeerDeps = JSON.parse(await exec('npm', opts));
  if (!peerDeps.has(name)) {
    peerDeps.set(name, new Map());
  }
  const currDeps = peerDeps.get(name);
  Object.entries(npmPeerDeps).forEach((entry) => {
    const [depName, depRange] = entry;
    log(`${depName}@${depRange}`);
    currDeps.set(depName, depRange);
  });
};

const getLocalPeerDep = async (range, name) => {
  log(`Getting peerDependencies for ${name}`);
  let packageInfo;
  try {
    // Hacktown, USA.
    // eslint-disable-next-line import/no-dynamic-require
    packageInfo = require(`${process.cwd()}/node_modules/${name}/package.json`);
  } catch (e) {
    return;
  }
  if (!packageInfo.peerDependencies) {
    return;
  }
  if (!peerDeps.has(name)) {
    peerDeps.set(name, new Map());
  }
  const currDeps = peerDeps.get(name);
  Object.entries(packageInfo.peerDependencies).forEach((entry) => {
    const [depName, depRange] = entry;
    log(`${depName}@${depRange}`);
    currDeps.set(depName, depRange);
  });
};

const getPeerDeps = async () => {
  const promises = [];
  if (USE_LOCAL_PEERDEPS) {
    log("Using local package.json's to determine peerDependencies.");
  } else {
    log('Using NPM to determine peerDependencies.');
  }
  deps.forEach((range, name) => {
    if (USE_LOCAL_PEERDEPS) {
      promises.push(getLocalPeerDep(range, name));
    } else {
      promises.push(getNpmPeerDep(range, name));
    }
  });
  return Promise.all(promises);
};

// peerDependencies checks
const checkPeerDependencies = async (peerDependencies, name) =>
  Promise.all(Array.from(peerDependencies.entries()).map(async (entry) => {
    const [peerDepName, peerDepRange] = entry;
    log(`Checking ${name}'s peerDependency of '${peerDepName}@${peerDepRange}'`);
    let found = false;
    if (deps.has(peerDepName)) {
      // Verify that the minimum allowed version still satisfies the peerDep
      const minAllowedVer = npmVers.get(peerDepName).minimum;
      if (semver.satisfies(minAllowedVer, peerDepRange)) {
        found = true;
      }
    }

    if (!found) {
      console.error(`A ${INCLUDE_DEV ? '[dev]D' : 'd'}ependency satisfying ${name}'s peerDependency of '${peerDepName}@${peerDepRange}' was not found!`);

      if (deps.has(peerDepName)) {
        console.log(`Current: ${peerDepName}@${deps.get(peerDepName)}`);
        const { versions } = npmVers.get(peerDepName);
        const maxUsabe = semver.maxSatisfying(versions, peerDepRange);
        console.log(`Required version is allowed? ${maxUsabe ? 'Yes' : 'No'}`);
      }
    }
  }));

const checkAllPeerDeps = async () => {
  const promises = [];
  peerDeps.forEach((peerDependencies, name) => {
    promises.push(checkPeerDependencies(peerDependencies, name));
  });
  return Promise.all(promises);
};

// Main function
async function checkPeerDeps() {
  // eslint-disable-next-line import/no-dynamic-require
  const packageConfig = require(`${process.cwd()}/package.json`);
  if (!packageConfig.dependencies) {
    console.error('No dependencies in the current pacakge!');
  }

  // Get the dependencies to process
  addDeps(packageConfig.dependencies);

  if (INCLUDE_DEV && packageConfig.devDependencies) {
    addDeps(packageConfig.devDependencies);
  }

  log('Dependencies:');
  deps.forEach((range, name) => { log(`${name}: ${range}`); });

  log('Determining peerDependencies...');
  await getPeerDeps();
  log('Done.');

  // Get the NPM versions required to check the peerDependencies
  log('Determining version ranges from NPM...');
  await getNpmVersions();
  log('Done.');

  log('Checking versions...');
  await checkAllPeerDeps();
  log('Done.');
}

module.exports = checkPeerDeps;<commit_msg>Ensure latest peerDependencies are checked<commit_after>const { exec } = require('sb-exec');
const semver = require('semver');

// Flags
// Enable debug output
const DEBUG = false;
// Include development packages when checking whether a peerDependency has been
// satisfied.
const INCLUDE_DEV = true;

// Internal vars
const deps = new Map();
const npmVers = new Map();
const peerDeps = new Map();

const log = (value) => {
  if (DEBUG) {
    console.log(value);
  }
};

const addDeps = (dependencies) => {
  Object.entries(dependencies).forEach((entry) => {
    const [name, range] = entry;
    deps.set(name, range);
  });
};

const gatherNpmVer = async (range, name) => {
  log(`Getting versions for ${name}@${range}...`);
  const opts = ['view', '--json', name, 'versions'];
  const versions = JSON.parse(await exec('npm', opts));
  const ranges = {
    versions,
    minimum: semver.minSatisfying(versions, range),
    maximum: semver.maxSatisfying(versions, range),
  };
  log(`${name}@${range}: '${ranges.minimum}' to '${ranges.maximum}'`);
  npmVers.set(name, ranges);
};

const getNpmVersions = async () => {
  // Gather the unique package names
  const toCheck = new Set();
  peerDeps.forEach((peerDependencies) => {
    peerDependencies.forEach((range, name) => {
      toCheck.add(name);
    });
  });

  // Grab the versions from NPM
  return Promise.all(Array.from(toCheck.values()).map(async (name) => {
    if (deps.has(name) && !npmVers.has(name)) {
      await gatherNpmVer(deps.get(name), name);
    }
  }));
};

const addPeerDeps = (name, peerDependencies) => {
  if (!peerDeps.has(name)) {
    peerDeps.set(name, new Map());
  }
  const currDeps = peerDeps.get(name);
  Object.entries(peerDependencies).forEach((entry) => {
    const [depName, depRange] = entry;
    log(`${name} peerDependency: ${depName}@${depRange}`);
    currDeps.set(depName, depRange);
  });
};

// Get the peerDependencies
const getNpmPeerDep = async (range, name) => {
  log(`Getting NPM peerDependencies for ${name}`);
  const opts = ['view', '--json', name, 'peerDependencies'];
  const npmPeerDeps = JSON.parse(await exec('npm', opts));
  addPeerDeps(name, npmPeerDeps);
};

const getPeerDep = async (range, name) => {
  log(`Getting peerDependencies for ${name}`);
  let packageInfo;
  try {
    // Hacktown, USA.
    // eslint-disable-next-line import/no-dynamic-require
    packageInfo = require(`${process.cwd()}/node_modules/${name}/package.json`);
  } catch (e) {
    return;
  }
  if (!packageInfo.peerDependencies) {
    return;
  }

  if (!npmVers.has(name)) {
    await gatherNpmVer(range, name);
  }
  if (semver.lt(packageInfo.version, npmVers.get(name).maximum)) {
    // The installed version isn't the highest allowed, check the latest from NPM
    log(`${name}: Installed version lower than allowed version. Using NPM to determine peerDependencies.`);
    await getNpmPeerDep(range, name);
  } else {
    log(`${name}: Using local package.json's to determine peerDependencies.`);
    addPeerDeps(name, packageInfo.peerDependencies);
  }
};

const getPeerDeps = async () => {
  const promises = [];
  deps.forEach((range, name) => {
    promises.push(getPeerDep(range, name));
  });
  return Promise.all(promises);
};

// peerDependencies checks
const checkPeerDependencies = async (peerDependencies, name) =>
  Promise.all(Array.from(peerDependencies.entries()).map(async (entry) => {
    const [peerDepName, peerDepRange] = entry;
    log(`Checking ${name}'s peerDependency of '${peerDepName}@${peerDepRange}'`);
    let found = false;
    if (deps.has(peerDepName)) {
      // Verify that the minimum allowed version still satisfies the peerDep
      const minAllowedVer = npmVers.get(peerDepName).minimum;
      if (semver.satisfies(minAllowedVer, peerDepRange)) {
        found = true;
      }
    }

    if (!found) {
      console.error(`A ${INCLUDE_DEV ? '[dev]D' : 'd'}ependency satisfying ${name}'s peerDependency of '${peerDepName}@${peerDepRange}' was not found!`);

      if (deps.has(peerDepName)) {
        console.log(`Current: ${peerDepName}@${deps.get(peerDepName)}`);
        const { versions } = npmVers.get(peerDepName);
        const maxUsabe = semver.maxSatisfying(versions, peerDepRange);
        console.log(`Required version is allowed? ${maxUsabe ? 'Yes' : 'No'}`);
      }
    }
  }));

const checkAllPeerDeps = async () => {
  const promises = [];
  peerDeps.forEach((peerDependencies, name) => {
    promises.push(checkPeerDependencies(peerDependencies, name));
  });
  return Promise.all(promises);
};

// Main function
async function checkPeerDeps() {
  // eslint-disable-next-line import/no-dynamic-require
  const packageConfig = require(`${process.cwd()}/package.json`);
  if (!packageConfig.dependencies) {
    console.error('No dependencies in the current pacakge!');
  }

  // Get the dependencies to process
  addDeps(packageConfig.dependencies);

  if (INCLUDE_DEV && packageConfig.devDependencies) {
    addDeps(packageConfig.devDependencies);
  }

  log('Dependencies:');
  deps.forEach((range, name) => { log(`${name}: ${range}`); });

  log('');

  log('Determining peerDependencies...');
  await getPeerDeps();
  log('Done.');

  log('');

  // Get the NPM versions required to check the peerDependencies
  log('Determining peerDependency version ranges from NPM...');
  await getNpmVersions();
  log('Done.');

  log('');

  log('Checking versions...');
  await checkAllPeerDeps();
  log('Done.');
}

module.exports = checkPeerDeps;
{'fraction_non_alphanumeric': 0.16436476721851276, 'fraction_numerical': 0.0, 'mean_word_length': 3.9009412819363516, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6155790', 'n_tokens_mistral': 3572, 'n_tokens_neox': 3504, 'n_words': 794}