Skip to content

Plugins ​

A plugin adds a group of actions to Tipeline — for example drupal.createContent or googledocs.createDoc — without changing Tipeline itself. Plugin steps work like built-in ones: in the builder, in workflow files, in apps and with the assistant.

Installing a plugin ​

  • From a hub: open Hub → Plugins and click Install, or run tipeline hub install plugin <hubId> <identifier>. See Hubs.
  • By hand: put the plugin's folder in ~/Tipeline/plugins/ (for example ~/Tipeline/plugins/drupal/index.mjs), then open Plugins. If it has a package.json with dependencies, run npm install in its folder first.

A new plugin is listed turned off, because its code runs inside Core with full access to your computer. Read it, or trust where it came from, then turn it on with its switch. Its actions are available right away.

Managing plugins ​

Plugins in the sidebar lists every plugin, with its version, author and switch. Opening the page rescans ~/Tipeline/plugins/. Turning a plugin off tells you which workflows use it: their steps can't run while it's off.

WarningWhat it meansWhat to do
Group conflictIts group is already used by a built-in group or another plugin, so it wasn't loadedRename group in the plugin's index.mjs, then restart Core
Folder missingIts folder was moved or deletedPut the folder back, or remove the listing

The examples in the repo's examples/plugins/ folder (greeting, invoicing, drupal, google-docs, text-case) are a good starting point.

Writing a plugin ​

A plugin is a folder with an index.mjs (or index.js) whose default export describes the group:

js
// ~/Tipeline/plugins/greeting/index.mjs
export default {
  group: 'greeting',                 // required — the action group, unique
  name: 'Greeting Plugin',
  description: 'Builds simple greeting and farewell messages.',
  author: 'Tipeline',
  version: '1.0.0',

  actions: {                         // required — one async function per action
    async sayHello(params) {
      const name = params?.name?.trim();
      if (!name) throw new Error('greeting.sayHello: "name" param is required');
      return `Hello, ${name}!`;
    },
  },

  params: {                          // the form the builder shows, and validation
    sayHello: [{ name: 'name', type: 'string', label: 'Name', required: true }],
  },
};
yaml
- group: greeting
  name: sayHello
  params:
    name: "{{ userName }}"
  destination: greeting

An action receives its parameters with templates already filled in, and returns its result. Throw an Error to fail the step; the message is shown in the run.

Export reference ​

KeyRequiredWhat it does
group✓The action group. Must not clash with a built-in group or another plugin.
actions✓{ actionName: async (params) => result }
name, description, author, versionShown on the Plugins page. version is free text.
imageA URL, or a path inside the plugin folder
paramsPer action: the fields the builder shows. Also turned into validation that runs before every step.
docsPer action: { description, example } shown in the builder
returnsPer action: the result's type (string, number, boolean, object, array, any), so the builder offers the right variables as destination
rulesPer action: fields that become required when another field has a value
cacheableAction names whose results may be cached

Parameter fields ​

js
params: {
  sendInvoice: [
    { name: 'email', type: 'string', label: 'Email', required: true, pattern: '^[^@]+@[^@]+$' },
    { name: 'currency', type: 'string', enum: ['USD', 'EUR'], default: 'USD' },
    { name: 'amount', type: 'number', min: 0, precision: 2 },
    { name: 'sendCopy', type: 'boolean', default: false },
    { name: 'ccEmail', type: 'string' },
    { name: 'connection', type: 'variable' },
  ],
},
rules: {
  sendInvoice: [{ when: { field: 'sendCopy', equals: true }, require: ['ccEmail'] }],
},
FieldMeaning
nameParameter name
typestring, number, boolean, date, html, or variable — a live value from an earlier step (a browser, a connection), picked from the step's variables and passed as {= name =}
componenttextarea for long text, datetime for a date and time
label, descriptionShown in the builder
default, requiredDefault value, and whether it must be set
enumAllowed values (strings); shown as a dropdown
patternA regular expression the string must match
min, maxNumber limits, or string length limits
precisionMaximum decimal places for a number

Every field except variable also accepts a {{ }} or {= =} template.

Credentials ​

Don't put keys or passwords in the plugin. Take them as parameters, so workflows can pass them from global variables or _env:

yaml
- group: drupal
  name: getContent
  params:
    baseUrl: "{{ _env.DRUPAL_BASE_URL }}"
    auth: "Basic {{ _global.drupalAuth }}"
    contentType: article
    uuid: "{{ uuid }}"

Trying it out ​

  1. Put the folder in ~/Tipeline/plugins/.
  2. Open Plugins (it rescans the folder) and turn the plugin on.
  3. Add one of its steps in the builder, or run a workflow file with tipeline workflow run.

After editing index.mjs, restart Core (tipeline stop, then tipeline start) to load the new code: Node keeps the first version of a module it imported.

Publishing ​

Zip the folder (with index.mjs at the root of the zip) and add it to a hub's hub.json with "type": "plugin" and its group. See Publishing to a Hub.

Released under the Apache License 2.0.