Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I load code from another Dart package, known only at runtime?

Tags:

dart

I am building a Dart application. It needs to load code from a third-party package, which is only known at runtime. My application needs to:

  1. auto-discover the dependency
  2. load a library from that dependency
  3. interact with the dependency

Ideally, I do not want to require that my users specify the third-party dependency. The application should auto-discover the dependency.

For example, a workflow could be something like this:

  1. User installs my app (pub global activate my_app)
  2. User installs a "plugin" (pub global activate plugin_for_my_app)
  3. User runs my app (my_app)
  4. The app auto-discovers that plugin_for_my_app exists.
  5. The app loads the plugin (via spawnUri perhaps?)
  6. The app calls into the plugin

Requirements:

  1. Must run from the command-line.
  2. Must work on Windows, Mac, Linux.
  3. Should (but doesn't have to) run when compiled to JavaScript.
  4. pub run support is optional (pub run makes it tricky, because it rewrites your import URIs, so it's not a requirement)

What's the best way to do this?

like image 914
Seth Ladd Avatar asked Feb 16 '15 19:02

Seth Ladd


1 Answers

In the plugins package, currently, there is no way to resolve dependencies through pub. When I originally designed the API it was assumed that the dependencies were already retrieved through pub get. With that said, plugin discovery on the file system is simple.

As you can see in the example in the README, loading plugins was as simple as new PluginManager().loadAll(String directory) which would automatically discover all plugins inside the directory and load them. This solution is ideal if all plugins are to be in one folder.

It is possible to do individual plugin directory loading as well, provided it follows the plugin directory structure. Using a PluginLoader you can load in a directory that contains the necessary files for a plugin to run properly. It is not necessary to call load() since the PluginManager will take care of calling in load for you.

A simplified way of loading a plugin

  1. Instantiate the PluginManager.

    PluginManager pm = new PluginManager();

  2. Determine the plugin you want loaded. The plugins library will automatically determine the pub cache directory. As per the documentation of pub, the PUB_CACHE environment variable is also supported.

  3. Load in the plugin. A Future is returned with a Plugin object that provides basic information about the plugin. The plugin requires a pubspec.yaml with a name, a packages directory, and a bin/main.dart source file. However we are loading from the pub cache, so we do not need to worry about the setup of the plugin, the only requirement is the package from the pub cache supports the plugins package.

pm.loadFromCache("test-1.0.0").then((Plugin plugin) {
    print("Plugin loaded!");
    handle();
});
  1. After all the plugins you desire to be loaded are initialized, the manager can now listen for requests properly. Simply use the listener to 'see' the incoming data.

The plugin side

The plugin simply uses a receiver as provided by the plugins API.

void main(List<String> args, SendPort port) {
    Receiver rec = new Receiver(port);
    rec.listen((Map<dynamic, dynamic> data) {
        print("Received data: $data");
    });
}
like image 103
samrg472 Avatar answered Oct 21 '22 07:10

samrg472