Plugins
Add your own actions to Mantidb with small, signed JavaScript plugins.
Plugins add actions to Mantidb's context menus. A plugin is a small JavaScript program that can read the table or rows you right-clicked, run queries (with your permission), copy text and show messages. Every plugin is signed, and you decide which ones to trust.
Manage plugins
Open Mantidb ▸ Settings… (⌘,) and choose Plugins.
The Installed list shows each plugin's name, version and author, description and signing status. For each plugin you can:
- Turn it on or off with the Enabled switch.
- Click Review… when a plugin needs your trust before it can run (see Signing and trust).
- Click Remove to uninstall it.
The pane also has these buttons:
- Install… — choose a
.mantidbpluginfolder to install. - Install Example — installs the example plugin.
- Show in Finder — opens the plugins folder.
Plugins are installed to ~/Library/Application Support/Mantidb/Plugins/.
Use a plugin
Plugin actions appear in two places, depending on the plugin:
- Tables — right-click a table or view in the sidebar.
- Rows — right-click rows in the data grid. The action receives the row you clicked, or the selected rows.
Plugin structure
A plugin is a folder named <id>.mantidbplugin:
com.example.tools.mantidbplugin/
├── manifest.json
├── signature.json
└── main.js
manifest.jsondescribes the plugin.signature.jsonholds its signature.main.js(or the file named inmain) is the plugin's code.
manifest.json
| Field | Description |
|---|---|
id | A unique reverse-DNS identifier, such as com.example.tools. |
name | The name shown in Settings. |
version | The plugin's version. |
author | Who made it. |
description | A short description. |
main | The JavaScript file to run. Defaults to main.js. |
permissions | Any of query, write and clipboard. write requires query. |
actions | The actions the plugin adds, each with an id, a title and its contexts. |
files | The SHA-256 hash of every file in the plugin. |
Each action's contexts lists where it appears: table for the sidebar menu of tables and views, rows for the grid menu.
{
"id": "com.example.tools",
"name": "Example Tools",
"version": "1.0.0",
"author": "You",
"description": "Copies rows as JSON and counts the rows of a table.",
"main": "main.js",
"permissions": ["query", "clipboard"],
"actions": [
{ "id": "copy-json", "title": "Copy as JSON", "contexts": ["rows"] },
{ "id": "count-rows", "title": "Count Rows", "contexts": ["table"] }
],
"files": {
"main.js": "<sha-256 of main.js>"
}
}
You don't fill in files by hand: mantidb-plugin sign writes the hashes and the signature for you (see The mantidb-plugin tool).
Signing and trust
Every plugin must be signed with an Ed25519 key. The signature covers the exact bytes of manifest.json, and the manifest lists the SHA-256 hash of every file. Mantidb refuses a plugin that is unsigned, has been modified, contains files that aren't listed, or contains symbolic links.
The first time you enable a plugin, Mantidb asks Trust “<name>”? and shows its key fingerprint (SHA256:…), the permissions it requests and the actions it adds. Click Trust and Enable to allow it.
Mantidb asks again when:
- the plugin is signed with a different key, or
- an update requests more permissions.
JavaScript API
Register a function for each action declared in the manifest. Rows arrive as arrays of values, in the same order as ctx.columns:
mantidb.registerAction("copy-json", async (ctx) => {
const names = ctx.columns.map((column) => column.name);
const objects = ctx.rows.map((row) =>
Object.fromEntries(row.map((value, i) => [names[i], value]))
);
await mantidb.copyToClipboard(JSON.stringify(objects, null, 2));
await mantidb.showMessage(`Copied ${ctx.rows.length} rows as JSON.`);
});
mantidb.registerAction("count-rows", async (ctx) => {
// qualifiedName is already quoted for the connection's dialect.
const result = await mantidb.query(`SELECT COUNT(*) FROM ${ctx.table.qualifiedName}`);
await mantidb.showMessage(`${ctx.table.name} has ${result.rows[0][0]} rows.`);
});
The context object
| Property | Description |
|---|---|
kind | Where the action was called from. |
connection | name, driver, environment and safeMode of the connection. |
schema | The current schema. |
table | schema, name, kind and qualifiedName of the table. |
columns | The columns of the rows. |
rows | The rows the action was called on. |
Functions
| Function | Description |
|---|---|
mantidb.registerAction(id, fn) | Runs fn(ctx) when the user picks the action id. |
mantidb.query(sql) | Runs one statement. Returns a promise with columns, columnTypes, rows, affectedRows and truncated. Needs the query permission. |
mantidb.copyToClipboard(text) | Copies text. Needs the clipboard permission. |
mantidb.showMessage(text) | Shows a message to the user. |
mantidb.log(...) / console.log(...) | Writes to the log. |
Writes with mantidb.query need the write permission, and Mantidb always asks you to approve each one, whatever the connection's safe mode.
Limits
- Each run can take up to 120 seconds, with at most 10 seconds of continuous synchronous work.
- Plugins have no network access, no file access, no timers and no
require.
Plugin actions can't be assigned keyboard shortcuts, and they don't appear in the SQL editor or in query results.
Example plugin
Click Install Example in Settings ▸ Plugins to install Markdown Tools (example). It adds two actions:
- Copy as Markdown Table — in the data grid's context menu.
- Count Rows — in the sidebar's context menu for tables.
It's a good starting point for your own plugin: click Show in Finder to look at its files.
The mantidb-plugin tool
Use the mantidb-plugin command-line tool to create a signing key, sign your plugin and check it before you share it:
# Create a signing key (once)
mantidb-plugin keygen ~/keys/plugins.key
# Sign the plugin after every change
mantidb-plugin sign com.example.tools.mantidbplugin ~/keys/plugins.key
# Check the signature and file hashes
mantidb-plugin verify com.example.tools.mantidbplugin
Keep your key file private: anyone who has it can sign plugins as you. If you sign with a different key, users are asked to trust the plugin again.
