Plugin structure

This page describes where the plugins are stored, how are they structured, and how they work.

Location

Plugins are stored in each app's {appData}/plugins directory. Comfy list of all paths used by Drovp and their exact locations for your installation (along with Open folder buttons) is available in app's About page.

Here are some generic locations for each system:

OSPath
WindowsC:\Users\{USERNAME}\AppData\Roaming\Drovp\plugins
Windows Portable{DROVP_DIRECTORY}\userData\plugins
Linux~/.config/Drovp/plugins
macOS~/Library/Application Support/Drovp/plugins

Installed plugins

All plugins installed from registry are stored inside the node_modules directory, and Drovp keeps track of them with package.json file. Unless you know what you're doing, don't touch these.

Local plugins

Local development plugins are node modules, each in their own folder in the root of the plugins directory.

Note: You can't install 2 modules with the same package.json:name. In other words, you can't have your plugin both installed from registry, and also loaded as a local development version, as they would overwrite each other's extensions. In this case, Drovp will load the local plugin, ignore the installed one, and display a warning about it.

Example directory tree

{appData}/plugins/
 ├ foo/            // local development plugin
 │  ├ index.js
 │  ├ package.json
 │  └ processor.js
 ├ node_modules/   // stuff installed and managed by drovp
 └ package.json    // record of installed stuff

Module structure

For the node module to become a valid Drovp plugin it has to fulfill these requirements:

  1. Name prefixed with drovp-.*
  2. Has to have drovpplugin or drovpdependency in packge.json:keywords array.
    Using drovpdependency instead of drovpplugin makes the module be recognized and loaded by Drovp, but it'll not show up in registry searches. This is for plugins that are only meant to provide dependencies to other plugins, and not be installed by users directly. Example: @drovp/ffmpeg.
  3. The main file of your plugin that extends Drovp needs to be a CommonJS module.
    This only applies to the main file, not actual processor files. Read more about this limitation below.

If this module is published to npm, it'll be discoverable and installable in the app's Registry section, as well as this website's Plugins page.

* If you don't prefix your plugin names with drovp- they'll still be installable, but there will be a warning icon next to the name, as breaking this convention is sketchy because it might be used to impersonate other plugins. If you're publishing your plugin under an @org, you still have to use the prefix in the name portion, like this: @org/drovp-plugin-name.

Node environments and caveats

Main and processor files are executed in different environments with different things to look out for.

Main file

The main plugin file (package.json:main) is the module responsible for extending Drovp, and is loaded inside the Electron's renderer process.

Current Electron version: 28.0.0

It has to be a CommonJS module, and CAN'T even use dynamic import() calls to load pure ES modules. This is because this file will be loaded in Electron's renderer process, which doesn't support ESM modules. There's unfortunately no other way around it, and no fixes on the horizon from Electron side. You can track the issue here: drovp/drovp#2.

If you need to use npm modules which are ESM only, you can write your code as an ES module, and transpile it with a tool like esbuild while configuring all native modules such as fs as external, so that esbuild leaves require calls for them untouched.

Example basic main file:

// package.json:main file
module.exports = (plugin) => {
    plugin.registerProcessor('name', {
        main: 'processor.js',
        ...
    });
};

Processor files

The processor.js from the example above will then run in its own raw Node.js process, which is spun and reused depending on processor's and app's configuration.

Processor files CAN be ES modules, or use import() calls to load ESM only npm modules.

If the processor requires a min Node.js version to be used, declare it in package.json:engines (details below) and Drovp will ensure it's satisfied before using the processor.

package.json config

Below is a list of all package.json properties that Drovp looks for and is utilizing in some way.

registry

App checks where the registry of the plugin is located. In case its github, it'll use its API to query releases and use that to display plugin's changelog inside the app.

Currently, only github releases are supported.

engines.node

While main plugin file will always run in Drovp's Electron renderer thread, engines.node can be used to require a min Node.js version the plugin's processor(s) need to function properly. Drovp will then make sure it's installed before processor can be used.

All processors use the same Node.js binary, so the only possible change is update to the newest, thus max limits are not allowed/supported.

Example:

{
    "engines": {
        "node": ">=14"
    }
}

engines.drovp

Same as engines.node but creates a requirement on a min version of Drovp. App than won't allow any of the plugin's processors to run unless it's updated to this version.

os

Plugins should support all systems, but in cases that's not possible or doesn't make sense, you can use this to limit which operating systems your plugin is allowed to run on. The plugin will still be installable on all systems, as npm's registry search API doesn't share manifest properties in results so Drovp can't see this before installation, but it will at least prevent the plugin to be used on an unsupported platform with an appropriate explanation.

os is an array of platform keywords:

PlatformKeyword
Windowswin32
Linuxlinux
macOSdarwin

Examples:

{
    "os": ["darwin", "linux"]
}

Only macOS and linux.

{
    "os": ["!win32"]
}

Same as above.

cpu

Tells Drovp that plugin's processor(s) will only run on specific CPUs.

Possible values: arm, arm64, ia32, mips,mipsel, ppc, ppc64, s390, s390x, x32, x64

Drovp is currently only built for x64, so this is at the moment quite redundant.

drovp.origin

Informs the app of the intended install origin for your local external plugins (plugins you're developing that will not be published to npm), as the app has no other way of knowing. If someone installs your plugin, the origin is inferred from the origin used to install the package, but that is not available for in-development plugins.

The only purpose of this is for the developers to be able to generate profile import codes with correct install origin for external plugins they're working on.

Valid origins are: <git-host>:<git-user>/<repo-name>, <git repo url>, <tarball url>

Supported git host shorthands are: github, gitlab, bitbucket

Example:

{
    "drovp": {
        "origin": "github:account/repo"
    }
}