<commit_before>// @flow
import type { Plugin } from '../types'
import { throwWith, isNotString } from './utils'
import { is, isNil, map, pipe, without } from 'ramda'
import shell from 'shelljs'

shell.config.silent = true

// the mask to use when searching for plugins in a directory
const PLUGIN_FILE_GLOB = '*.js'

// is this file missing?
const isFileMissing = path => !shell.test('-e', path)

// is this a directory
const isNotDirectory = path => !shell.test('-d', path)

// try loading this module
function getPluginInitializer (path: string): ?Function {
  try {
    require.resolve(path)
    return require(path).default
  } catch (e) {
    return null
  }
}

/**
 * Creates a plugin.
 *
 * @param {string} path - The full path to the plugin.
 * @returns {Plugin}
 */
export function loadPlugin (path: string): Plugin {
  // sanity
  throwWith('path is required', isNil, path)
  throwWith('path must be a string', isNotString, path)

  // TODO: load the config
  const config = {}
  const plugin: Plugin = {
    config,
    path,
    initializer: null,
    error: null,
    errorMessage: null,
    status: 'Error'
  }

  // is the file missing?
  if (isFileMissing(path)) {
    plugin.status = 'Error'
    plugin.error = 'Missing'
  } else {
    // attempt to load the plugin
    plugin.initializer = getPluginInitializer(path)

    // did we load it properly?
    if (is(Function, plugin.initializer)) {
      plugin.status = 'Loaded'
    } else {
      plugin.status = 'Error'
      plugin.error = 'Invalid'
    }
  }

  return plugin
}

/**
 * Gets the names of the files in the given directory.
 */
function getFiles (path: string): Array<string> {
  shell.pushd(path)
  const dirs = shell.ls(PLUGIN_FILE_GLOB).map(x => `${path}/${x}`)
  shell.popd()
  return dirs
}

/**
 * Loads all the plugins in the given directory.
 *
 * @export
 * @param {string} path - The path to search
 * @returns {Array<Plugin>}
 */
export function loadPluginDirectory (path: string): Array<Plugin> {
  // sanity
  throwWith('directory path is required', isNil, path)
  throwWith('directory path must be a string', isNotString, path)
  throwWith('directory path must be a string', isNotDirectory, path)
  //  grab all the files
  return pipe(
    map(pluginPath => { try { return loadPlugin(pluginPath) } catch (e) { return null } }),
    without([null])
  )(getFiles(path))
}

/**
 * Creates a loaded plugin, great for testing.
 */
export function createLoadedPlugin (initializer) {
  return {
    initializer,<commit_msg>Adds missing annotations to createLoadedPlugin.<commit_after>// @flow
import type { Plugin } from '../types'
import { throwWith, isNotString } from './utils'
import { is, isNil, map, pipe, without } from 'ramda'
import shell from 'shelljs'

shell.config.silent = true

// the mask to use when searching for plugins in a directory
const PLUGIN_FILE_GLOB = '*.js'

// is this file missing?
const isFileMissing = path => !shell.test('-e', path)

// is this a directory
const isNotDirectory = path => !shell.test('-d', path)

// try loading this module
function getPluginInitializer (path: string): ?Function {
  try {
    require.resolve(path)
    return require(path).default
  } catch (e) {
    return null
  }
}

/**
 * Creates a plugin.
 *
 * @param {string} path - The full path to the plugin.
 * @returns {Plugin}
 */
export function loadPlugin (path: string): Plugin {
  // sanity
  throwWith('path is required', isNil, path)
  throwWith('path must be a string', isNotString, path)

  // TODO: load the config
  const config = {}
  const plugin: Plugin = {
    config,
    path,
    initializer: null,
    error: null,
    errorMessage: null,
    status: 'Error'
  }

  // is the file missing?
  if (isFileMissing(path)) {
    plugin.status = 'Error'
    plugin.error = 'Missing'
  } else {
    // attempt to load the plugin
    plugin.initializer = getPluginInitializer(path)

    // did we load it properly?
    if (is(Function, plugin.initializer)) {
      plugin.status = 'Loaded'
    } else {
      plugin.status = 'Error'
      plugin.error = 'Invalid'
    }
  }

  return plugin
}

/**
 * Gets the names of the files in the given directory.
 */
function getFiles (path: string): Array<string> {
  shell.pushd(path)
  const dirs = shell.ls(PLUGIN_FILE_GLOB).map(x => `${path}/${x}`)
  shell.popd()
  return dirs
}

/**
 * Loads all the plugins in the given directory.
 *
 * @export
 * @param {string} path - The path to search
 * @returns {Array<Plugin>}
 */
export function loadPluginDirectory (path: string): Array<Plugin> {
  // sanity
  throwWith('directory path is required', isNil, path)
  throwWith('directory path must be a string', isNotString, path)
  throwWith('directory path must be a string', isNotDirectory, path)
  //  grab all the files
  return pipe(
    map(pluginPath => { try { return loadPlugin(pluginPath) } catch (e) { return null } }),
    without([null])
  )(getFiles(path))
}

/**
 * Creates a loaded plugin, great for testing.
 */
export function createLoadedPlugin (initializer :Function): Plugin {
  return {
    initializer,
{'fraction_non_alphanumeric': 0.1285939346199291, 'fraction_numerical': 0.0, 'mean_word_length': 3.2609060402684564, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 17, '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': '3081777', 'n_tokens_mistral': 1589, 'n_tokens_neox': 1568, 'n_words': 527}