abigailjs/abigail

View on GitHub
src/utils.js

Summary

Maintainability
A
0 mins
Test Coverage
// dependencies
import { lookupSync } from 'climb-lookup';
import { dirname, resolve as resolvePaths } from 'path';
import { readFileSync } from 'fs';

/**
* @param {string} cwd - a starting position
* @returns {object} information - the lookup result
*/
export function lookupJson(cwd) {
  let path;
  try {
    path = lookupSync('package.json', { cwd });
  } catch (e) {
    path = null;
    const dir = null;
    const data = { scripts: {} };
    const options = {};

    return {
      path, dir, data, options,
    };
  }

  const dir = dirname(path);
  const data = JSON.parse(readFileSync(path));
  const options = data.abigail || {};

  return {
    path, dir, data, options,
  };
}

/**
* @param {object} [args] - a key-value defines
* @param {boolean} [options] - a extra behaviors
* @param {boolean} [options.enableIfObject=false] - if true and fieldValue is object, plugin to enable
* @returns {object} pluginOptions - the plugin options
*/
export function resolvePluginOptions(args = {}, options = { enableIfObject: false }) {
  const pluginOptions = {};

  Object.keys(args).forEach((key) => {
    if (Object.prototype.hasOwnProperty.call(args, key) === false) {
      return;
    }
    if (args[key] === null || args[key] === undefined) {
      return;
    }

    const fieldValue = args[key];
    if (typeof fieldValue === 'object') {
      if (options.enableIfObject) {
        fieldValue.enable = true;
      }
      pluginOptions[key] = fieldValue;
      return;
    }

    const opts = {};
    if (typeof fieldValue === 'boolean') {
      opts.enable = fieldValue;
    }
    if (typeof fieldValue !== 'boolean') {
      opts.enable = true;
      opts.value = fieldValue;
    }
    pluginOptions[key] = opts;
  });

  return pluginOptions;
}

/**
* @param {string} name - a plugin name
* @param {function} [constructor=undefined] - a plugin constructor
* @returns {function} constructor - the plugin constructor
*/
export function resolvePlugin(name, constructor) {
  if (typeof constructor === 'function') {
    return constructor;
  }
  if (name.match(/^[\w-]+$/) === null) {
    return require(resolvePaths(process.cwd(), name));
  }
  if (name.match(/^abigail-plugin/)) {
    return require(name);
  }

  return require(`abigail-plugin-${name}`);
}

/**
* @param {AsyncEmitter} parent - a abigail instance
* @param {object} options - a name-option as key-value for plugin
* @returns {object} plugins - the plugin instances
*/
export function loadPlugins(parent, options = {}) {
  const plugins = {};

  Object.keys(options).forEach((name) => {
    if (Object.prototype.hasOwnProperty.call(options, name) === false) {
      return;
    }

    const pluginOpts = options[name];
    if (pluginOpts.enable === false) {
      return;
    }

    const Plugin = resolvePlugin(name, pluginOpts);
    const plugin = new Plugin(parent, pluginOpts.value, pluginOpts);
    plugins[plugin.name] = plugin;
  });

  return plugins;
}