Skip to content

Extended "plugin" interface #24

Description

@spion-h4

We can extend the plugin interface in a backward compatible way to support several application phases:

  1. Support app.initialize(). Once all plugins are loaded, the initialize method can be called. This method will in turn call every plugin which returned a method called initialize from its construction function. The method can return a promise.

  2. Support app.terminate(). Similar to initialize but it will shut all plugins down. Analogously to initialize it will call a termination method on all plugins that have one

My main doubt about this design is how to make it clear which things go where, especially the config vs initialization phases. Perhaps we could support passing an object to load() in addition to a function - if an object is passed, it has to at least have an initialize method (that can return a promise), and it can optionally have a configuration getter that returns the env variables specs (once loaded it will be replaced with a cached property) as well as a terminate method (that can return a promise)

Activity

  1. changed the title [-]Plugin interface[/-] [+]Extended "plugin" interface[/+] on Apr 3, 2019
  2. spion-h4 commented on Apr 5, 2019

    @spion-h4
    CollaboratorAuthor

    new Load method:

    loadConfigurable({ configure(app:App):void; create(app:App) => void})

    Not sure if good idea to give access to the entire app in configure. Maybe just envaridator?

  3. spion commented on Apr 8, 2019

    @spion
    Contributor

    If its just envaridator, you'd probably need this interface:

    interface ConfigururablePlugin<T, U> {
      configure(env: Envaridator):T;
      create(app: App, config:T):U;
    }
  4. spion-h4 commented on Apr 9, 2019

    @spion-h4
    CollaboratorAuthor

    Another alternative making it easier to fetch this

    class EnvConfig extends AppSingleton {
      protected env = this.getSingleton(Envaridator);
    }
    
    class App {
      addConfigurablePlugin(item) {
        this.getSingleton(item.envConfig);
        this.uninitialized.push(item.create);
      }
      addPlugin(item) {
        this.uninitialized.push(item);
      }
      setupPlugins() {
        this.uninitialized.forEach(item => this.getSingleton(item));
      }
    }

    Plugin:

    class MyEnvConfig extends EnvConfig {
      myvar1 = this.env.register('name', {...})
      myvar2 = this.env.register('othername', {...})
      myvar3 = this.env.register('thirdname', {...})
    }
    
    let ConfigurablePlugin = {
      config: MyEnvConfig, 
      create: app => {
        let serviceInstallName = app.getSingleton(MyEnvConfig).serviceName.value;
        app.getSingleton(RPCServiceRegistry).add(serviceInstallNamevalue, MyService)
      }
    };

    App:

    class MyApp extends App {
      setupPlugins() {
        this.addPlugin(z);
        this.addConfigurablePlugin(ConfigurablePlugin);
      }
    
      // Maybe instead:
      // app.overrideSingleton(Envaridator, TestEnvaridator); 
      // where validate is always OK?
      initializeForTests() {
        this.setupPlugins()
        this.loadPlugins();
      }
    
      start() {
        this.setupPlugins();
        this.getSingleton(Envaridator).validateEnv();
        this.loadPlugins();
      }
    
      help() {
        this.getSingleton(Envaridator).showHelpSomething()
      }
    }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions