Skip to content

Pluggable CLI #121

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
jasonkuhrt opened this issue Dec 3, 2019 · 3 comments
Open

Pluggable CLI #121

jasonkuhrt opened this issue Dec 3, 2019 · 3 comments

Comments

@jasonkuhrt
Copy link
Member

Currently CLI cannot be plugged into. Prisma is an internal plugin, except for the CLI aspect which cheats, importing prisma logic.

A challenge will be the schism between cli and app. A CLI does not obviously know about this in code:

app.use(myPlugin)

possible solution areas

  • code-reflection (cli analyzes app code for use statements to know which plugins to activate in the cli
  • package.json/pumpkins-file config that opts-in to making cli use a plugin in the cli
  • same as above, but opt-out, automatically using any pumpkins-plugin-* package.

Also think about where the config can live, e.g.:

app.use(myPlugin({...}))

Does the user configure the plugin cli behaviour here? That would mean, again, code reflection.

@jasonkuhrt
Copy link
Member Author

jasonkuhrt commented Dec 5, 2019

  • all direct dependencies (listed in package.json) that have prefix name pumpkins-plugin- will get automatically instantiated and used.

    This means the following are the same:

    { "dependencies": { "pumpkins-plugin-foo": "1.2.3" }  }
    import { app } from 'pumpkins'
    import * as PumpkinsPluginFoo from 'pumpkins-plugin-foo'
    
    app.use(PumpkinsPluginFoo.create({}))

    This means we need some rules:

    1. A pumpkins plugin must export a named create function
    2. A pumpkins plugin must accept an input object for configuration
    3. A pumpkins plugin must have defaults for every option

    These rules make plugin creation and consumption predictable which is a highly desirable trait for a streamlined ecosystem. Even before automation is considered, we benefit from strong conventions here.

  • an escape hatch is needed to disable auto-use behaviour. The following could work:

      import { app } from 'pumpkins'
    
      app.unuse('foo')
  • There is an asymmetry in the use/unuse APIs. Think about this.

  • Maybe we have an API like this:

    import { app } from 'pumpkins'
    
    app.plugins.foo.configure()
    app.plugins.foo.enable()
    app.plugins.foo.disable()

    plugins would be a proxy and its properties would have autocomplete thanks to type-generation.

    this would make for a very high level developer experience to work with plugins:

    1. yarn add pumpkins-plugin-prisma
    2. app.plugins.prisma <-- <magically appears here>
  • another convention we should enforce is that plugin package name suffix is the identifier that will be used. Again making strong predictable conventions only helps the community, tooling, discoverability, so on.

@jasonkuhrt
Copy link
Member Author

jasonkuhrt commented Dec 6, 2019

  • cli execution path is apart from that of codebase
  • this means it is not obvious how an api for plugins will support plugging into the cli, where that api does not naturally exist
  • the approach we can take however is one of typegen
  • firstly, given plugin-auto-use, the simplest case, nothing need be done
  • however once a user wants to configure their plugin's behaviour, some kind of api is required. A natural place for the user would be the app. Technically it could also be a static external config file too, e.g. package.json
  • typegen is idiomatic to our worldview, so lets work with that approach, see where it gets us.
  • some examples

@jasonkuhrt
Copy link
Member Author

Significant progress made. API aspect remains to be done. But dynamic plugin loading based on package name pattern is now done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant