<commit_before>require('colors');
const glob = require('glob');
const fs = require('fs');
const path = require('path');

const FEATURES_PROJECT_DIR = path.join('sauce', 'features');
const FEATURES_INDEX_PROJECT_PATH = path.join(FEATURES_PROJECT_DIR, 'index.js');

function run(callback) {
  glob(`${FEATURES_PROJECT_DIR}/*/**/index.js`, (error, files) => {
    if (error) return callback(error);

    let imports = [];
    let featureNames = [];

    files.forEach((filePath) => {
      const filePathSplit = filePath.split('/');
      const projectFeaturePath = filePathSplit.slice(0, filePathSplit.length - 1).join(path.sep);

      // up one directory to use the project path
      let featureSetting = require(path.join('..', projectFeaturePath, 'settings.js')); // eslint-disable-line global-require

      if (Array.isArray(featureSetting)) {
        featureSetting = featureSetting[0];
      }

      // features/index will source from the features folder, so remove
      // `sauce/features` from the path here.
      const featureIndexPath = filePathSplit.slice(2, filePathSplit.length - 1).join('/');
      const importLine = `import { ${featureSetting.name} } from './${featureIndexPath}';\n`;
      imports.push(importLine);
      featureNames.push(featureSetting.name);
    });

    writeFeatureIndex(imports, featureNames, callback);
  });
}

function writeFeatureIndex(importLines, featureNames, callback) {
  const fileContents = `/*
 ***********************************************************
 * Warning: This is a file generated by the build process. *
 *                                                         *
 * Any changes you make manually will be overwritten       *
 * the next time you run webpack!                          *
 ***********************************************************
*/
${importLines.join('')}
const features = [
  ${featureNames.join(',\n  ')}
];

export default features;
`;

  const featureIndexPath = path.join(__dirname, '..', FEATURES_INDEX_PROJECT_PATH);
  fs.writeFile(featureIndexPath, fileContents, callback);
}

run(error => {
  if (error) {
    console.log(`Error: ${error}`.red);
    process.exit(1);
  }

  process.exit();
});
<commit_msg>Added error checking to `generateFeatureIndex` task so when typos are present you don't get a `Feature is not a constructor` error, instead it tells you exactly where the error is.<commit_after>require('colors');
const glob = require('glob');
const fs = require('fs');
const path = require('path');

const FEATURES_PROJECT_DIR = path.join('sauce', 'features');
const FEATURES_INDEX_PROJECT_PATH = path.join(FEATURES_PROJECT_DIR, 'index.js');

function run(callback) {
  glob(`${FEATURES_PROJECT_DIR}/*/**/index.js`, (error, files) => {
    if (error) return callback(error);

    let imports = [];
    let errorCheckingLines = [];
    let featureNames = [];

    files.forEach((filePath) => {
      const filePathSplit = filePath.split('/');
      const projectFeaturePath = filePathSplit.slice(0, filePathSplit.length - 1).join(path.sep);

      // up one directory to use the project path
      let featureSetting = require(path.join('..', projectFeaturePath, 'settings.js')); // eslint-disable-line global-require

      if (Array.isArray(featureSetting)) {
        featureSetting = featureSetting[0];
      }

      // features/index will source from the features folder, so remove
      // `sauce/features` from the path here.
      const featureIndexPath = filePathSplit.slice(2, filePathSplit.length - 1).join('/');
      const importLine = `import { ${featureSetting.name} } from './${featureIndexPath}';`;
      imports.push(importLine);

      const errorCheckingLine = `if (!${featureSetting.name}) { throw new Error('${featureSetting.name} feature failed to import. Have you set the name in the settings.js file to match the class name?'); }`;
      errorCheckingLines.push(errorCheckingLine);

      featureNames.push(featureSetting.name);
    });

    writeFeatureIndex(imports, errorCheckingLines, featureNames, callback);
  });
}

function writeFeatureIndex(importLines, errorCheckingLines, featureNames, callback) {
  const fileContents = `/*
 ***********************************************************
 * Warning: This is a file generated by the build process. *
 *                                                         *
 * Any changes you make manually will be overwritten       *
 * the next time you run webpack!                          *
 ***********************************************************
*/
${importLines.join('\n')}

${errorCheckingLines.join('\n')}

const features = [
  ${featureNames.join(',\n  ')}
];

export default features;
`;

  const featureIndexPath = path.join(__dirname, '..', FEATURES_INDEX_PROJECT_PATH);
  fs.writeFile(featureIndexPath, fileContents, callback);
}

run(error => {
  if (error) {
    console.log(`Error: ${error}`.red);
    process.exit(1);
  }

  process.exit();
});

{'fraction_non_alphanumeric': 0.1799959505972869, 'fraction_numerical': 0.0024296416278598906, 'mean_word_length': 3.5404411764705883, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2736568', 'n_tokens_mistral': 1388, 'n_tokens_neox': 1364, 'n_words': 340}