Getting started with plugin development

This page will describe the practical steps required to create a plug-in from a GitHub repository and published as an NPM package. We will use a minimal example based on adding a new datatype for angular degrees. The finished example is available as the saltcorn/angles-type repository on GitHub. Note that you do not have to use GitHub or for that matter any kind of version control, you can use any other method you are familiar with for creating an NPM package.

1. Create a GitHub repository

Create a GitHub repository on the your account. You should add a .gitignore file based on the Node template. If you are contributing this to the Saltcorn store, you will also need to choose a licence. Clone this repository into your home directory. For the example repository name, to clone this repository in my home directory I run on the command line: git clone [email protected]:saltcorn/angles-type.git. If you enter this directory (cd angles-type) and list the files (ls) there should now only be a single file present: the LICENCE file.

2. Create package and index files

You need to create at least two files in your new package: the package.json which describes the contents of the NPM package, and a JavaScript file containing the code for the plug-in. We will call this JavaScript file index.js but you can give it a different name as long as you put the chosen filename in the main field in the package.json. Typically, the JavaScript file is either called index.js or it is the name of the plug-in followed by .js but this is just our convention.

The package.json should look something like this:

{
  "name": "saltcorn-angles-type",
  "version": "0.1.0",
  "description": "Angular degrees data type",
  "main": "index.js",
  "dependencies": {},
  "author": "Tom Nielsen",
  "license": "MIT",
  "repository": "github:saltcorn/angles-type",
  "publishConfig": {
    "access": "public"
  }
}

The name field is the name of the NPM package (this does not have to match your repository name).

You should list any Saltcorn packages you are going to import modules from under dependencies.

A blank module JavaScript file (in our case, index.js) need only export an object with a single field sc_plugin_api_version indicating the version of the Saltcorn plug-in API used. Currently, only one version is supported, version 1. Therefore our minimal plug-in which does absolutely nothing, has the following JavaScript file (index.js):

module.exports = { sc_plugin_api_version: 1 };

Let's load this into a locally running Saltcorn instance so we can check that the plug-in load correctly.

3. Installing a local plugin

Make sure you are running Saltcorn locally on your desktop, either a development environment based on SQLite or with a PostgreSQL server running in the background. Also make sure you are logged in to an account with administrative privileges.

Go to the "Plugins" menu option under "Settings". Near the top right hand corner, there is a button with three dots that expand into a drop-down menu. Choose the option "Add another plugin" (because we will be installing a plug-in that is not in the store) from this menu. Add another plug-in screenshot

You will then see a form that lets you enter the details of a plug-in. Choose these options:

  • Name: the name of the plug-in as you specified it in the name field in the package.json file, here "saltcorn-angles-type".
  • Source: choose "local"
  • Location: enter the full path to the directory that contains your plug-in. It does not matter whether you end in a slash or not

Then click Create. If everything works, then after a few seconds you should be directed back to the plug-in store with a success message: "Plugin saltcorn-angles-type installed".

Alternatively (easier, 2024):

if your local plugin is cloned in your home directory, you can install it on the command line with:

saltcorn install-plugin -d /path/to-plugin

You can also swap between local and npm installs. Use

saltcorn dev:localize-plugin /path/to/plugin

To change a plug-in that has been installed from NPM via the module store to running off a local checkout. Use 

saltcorn dev:localize-plugin -u

To go the other way to convert a local install to npm install

4. Running server while developing

We are currently using this command to run in development mode

npm run tsc; while [ 1 ]; do SALTCORN_NWORKERS=1 saltcorn serve --dev;done

This will restart the server whenever you save changes to a file from a local plug-in or from the core saltcorn code

5. Commit and publish

Because this part of the tutorial is about the practical aspects, we will now see how to publish this (entirely useless) plugin. In the next part we will actually be defining our new datatype.

As we have made a little bit of progress, setting up the plug-in directory structure, we should now commit with git and push to GitHub. If you are using the git command line, run git commit -am 'blank plugin' && git push. If you're using a graphical git client, perform the equivalent actions.

To publish this to NPM, you should have an NPM account set up and be logged in from the command line with npm login - you only have to do this once and it will remember your login, even after you restart your computer. To publish your plug-in, run npm publish. If you are publishing under an organisation, you may get an error message stating that payment is required. Simply run again with npm publish --access=public.

6. Beware dragons

In former example of package.json above there was dependencies of saltcorn packages (namely data and markup), but there are bug in npm that forces you to skip this dependecies ever if eslint insists:

It you adding, for example, @saltcorn/data to package.json, it will be installed to your plugin's node_modules and will be different than one that used by saltcorn itself. It's impractical but harmful for stateless packages like @saltcorn/markup, but very dangerous for data, server, db-common and so on. I.e. getState() will return non-initialized singleton instead of actual tenant state, and so on.