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 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. Use CommonJS module exports. The ESModule (import from) syntax is not supported yet (drovp/drovp#2).

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.

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: 15.3.3

This also comes with a pretty big limitation that it has to be a CommonJS module, and CAN'T even use dynamic import() calls to load pure ES modules. This limitation is due to Electron being quite behind the curve regarding node ES modules. The import() we have access to in the renderer process is the basic front-end browser version of the import() that can't resolve node module identifiers. This will hopefully get resolved soon (you can track the progress here: drovp/drovp#2).

Alternatively, you can write your code as ES modules, and use a bundler such as esbuild to bundle the whole main file and its dependencies into a single file, just don't forget to set the native modules such as fs as external, so that esbuild leaves require calls for them.

Example:

// 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.

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"
    }
}

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"
    }
}