actions

An action is a building block usable inside of a Marjory workflow

The actions directory contains your actions functions. Marjory reads all the .js files inside this directory and automatically creates the actions for you.

An action is and exported function that exists inside of the actions folder. You do not have to write only one action per file, but we recommend doing so as it will keep your code clean.

If you do not export your function, it will not be defined as an action

// This is an action, because it's exported
export const getPancakes = (data, credentials) =>
  new ModuleResponse({ pancakes: ["🥞", "🥞", "🥞", "🥞"] });

// This is not an action, because it's not exported
const getPancake = (data, credentials) => new ModuleResponse({ pancake: "🥞" });

Properties

data

The property data contains all the inputs of an action. To know more about prescript, see How to add and configure a service action

Here is an example of a marjory.yml action section and the object you can work with in an action function:

...
actions:
  getPancake:
    name: Get Pancake
    inputs:
      topping:
        type: string
        descripton: The topping you want on your pancake
        required: true
        example: BUTTER
...

credentials

The property credentials contains all the credentials information defined when the module was installed by someone. The list of given credentials are defined in the marjory.yml file.

Here is an example of a marjory.yml credentials section and the object you can work with in an action function:

...
credentials:
  apiKey:
    type: string
    isCrypt: true
    description: The api key to work with the Pancake API
...

SDK

ModuleResponse

ModuleResponse is a simple class allowing you to return data (object or basic type) to the next action in the workflow. This will return an object with the data passed and a status code of 200.

ModuleError

ModuleError is to handle your action errors, it's like an HTTP error. Here is an example:

import Marjory from "marjory";

export const getPancake = (data) => {
  var pancake = getPancake(data.id);
  
  if (!pancake)
    throw new Marjory.ModuleError(404, `No pancake with id ${data.id}`);

  return new Marjory.ModuleResponse(response);
}

If no pancake is found, this will return an object with a 404 status code and a data object containing the message.

Store

If an action has multiple steps (ie: multiple API calls), you might want to store data between steps in case your action fails and an operator needs to restart it.

To save the data during an action, you can use our Store object in the SDK. Here is an example:

import Marjory from "marjory";

export const multiStepAction = async (data) => {
  var company = Marjory.Store.company;

  // step 1
  if (!company) {
    company = await createCompany(data).catch((e) => {
      throw new Marjory.ModuleError(e.code, e.message);
    });
    
    // Store the new company
    Marjory.Store["company"] = company;
  }

  // step 2
  return billCompany(Store.company, 355, "€")
    .then((data) => new Marjory.ModuleResponse(data))
    .catch((e) => {
      throw new Marjory.ModuleError(e.code, e.message);
    });
}

In this example, we have a step we want to do only once (the creation part) even if the rest of the action (the billing parts) fails. So by storing the company in the Store, if we rerun the action in a workflow, we won't create the company again.

Storage

You might need to keep storage between multiple action execution for the same operator. You can do so by using the DB object of the SDK.

Here is all the functions you can use on the DB object:

import Marjory from "marjory";

export const action = (data, credentials) => {
    constDB= Marjory;
    
    // Search
    DB.collection('pancakes').find();
    DB.collection('pancakes').findOne();
    
    // Insertion
    DB.collection('pancakes').insertOne();
    DB.collection('pancakes').insertMany();
    
    // Update
    DB.collection('pancakes').updateOne();
    DB.collection('pancakes').updateMany();
    DB.collection('pancakes').replaceOne();
    DB.collection('pancakes').findOneAndUpdate();
    DB.collection('pancakes').findOneAndReplace();
    
    // Deletion
    DB.collection('pancakes').deleteOne();
    DB.collection('pancakes').deleteMany();
    DB.collection('pancakes').findOneAndDelete();
    
    // Stats
    DB.collection('pancakes').countDocuments();
    DB.collection('pancakes').estimatedDocumentCount();
}

Do not use const { DB } = Marjory from outside your function

Behind the DB object is a MongoDB instance. You can learn more on how to use these functions directly from mongo documentation.

Last updated