Skip to content

Plugin architecture

Jeffrey Wear edited this page May 18, 2019 · 9 revisions

Tasks tracked here.

Options

js-plugins

The only plugin "framework" I can find online is js-plugins. Pros:

  • nice conceptual model (particularly the extension point bit)
  • plugins are automatically registered with the host app (depending on how the host app "scans" for plugins)

Cons:

  • doesn't appear to support configuration files, i.e. user can't whitelist plugins—all host plugins in a given install directory will be loaded
  • plugin configuration is defined in package.json, which makes sense given the framework's model; but would be nice if everything could be defined in the main export

Own framework

Given the limitations of js-plugins, I think we should explore defining our own plugin framework, configured like ESLint but possibly with a conceptual model similar to js-plugins' (need to look into what ESLint's looks like).

By default this would use a configuration file located located at ~/.custodyclirc but we could support local configuration files or a -c flag in the future.

It would be nice if globally-installed plugins could offer to register themselves into that file, possibly using is-installed-globally.

Plugin API

Users

Custody

  • custody.debug === debug(msg) { screen.debug(msg); }.

Plugins

  • Return an object e.g. { commands } (like Babel) or call an explicit API e.g. custody.addCommand (like…)?

Commands

commands(process, state) {
  return [
    [shortcut, commandDescription]  // Ex: [opts.key || 't', new RestartServer(process)]
  ];
]
class RestartServer {
  // TODO
  static async supports(process) {
	const cwd = await getWorkingDirectory(process);
    try {
      statSync(path.join(cwd, 'app.js'));
      return true;
    } catch (e) {
      if (e.code === 'ENOENT') {
        return false;
      }
      throw e;
    }   
  }

  constructor(process) {
    this.process = process;
  }

  get verb() {
    return 'restart (just the server)';
  }

  async toggle() {
    const cwd = await getWorkingDirectory(this.process);
    return exec('touch app.js', { cwd });
  }
}

Notes

  • Don't cache process objects (link)
  • Try to conditionalize commands (link)
  • Which plugins are suitable for inclusion in the @custody scope (link)
  • When to call setNeedsReload (link)
  • Use debug vs. console.log, and how (link)
Clone this wiki locally