Functions:Definitions - bettyblocks/cli GitHub Wiki

Function Definition

A Function Definition describes the input and output of your function. It determines how the IDE renders the ActionStep that is based on the function. And it tells the IDE what values a no-coder can or must configure for the function to work properly.

Given an application cli-wiki and a function called say-hello, you can find the function definition in cli-wiki/functions/say-hello/1.0/function.json. See new on how to create a new function.

This Function Definition follows strict guidelines, based on the JSON Schema. The JSON Schema can be a bit intimidating at first sight, so we've added several examples below to help you get started.

Function

Example: New Function

cli-wiki/functions/exampleFunction/1.0/function.json:

{
  "label": "Example Function",
  "description": "Description",
  "category": "Misc",
  "icon": {
    "name": "ActionsIcon",
    "color": "Orange"
  },
  "options": [],
  "yields": "NONE"
}

cli-wiki/functions/exampleFunction/1.0/index.js:

const exampleFunction = async () => {
  // Your implementation
};

export default exampleFunction;

Function setup

Please note that the function needs to be asynchronous. Given that your function is named sayHello and it accepts no options, your function head could look like this:

  const sayHello = async () => {

The return value should be a named object corresponding to the blueprint (function.json). Given that your function has an output option that is called greet:

return { greet: "Hello world!" };

You should export the function as default at the bottom of the file:

export default sayHello;

If your function has (input) options, then your function should receive a named object as a first argument. Given that your function accepts an input option called name:

  const sayHello = async ({ name }) => {

If your function yields child steps, your function should receive a second argument that is an asynchronous function you can invoke / await:

  const doSomethingWithChildSteps = async (_, steps) => {
    await steps();

If your functions yields paths, the second argument will be an object on which you can await the forEach function for executing each path:

const condition = async (_, paths) => {
  await paths.forEach(async ({ value, steps }, halt) => {
    if (value) {
      await steps();
      halt();
    }
  });
};

See our native functions for all kinds of examples.

Options

For more information about the available options you can also check the JSON Schema

Input

Example: Action

cli-wiki/functions/exampleFunction/1.0/function.json:

{
  "label": "Example Function",
  "description": "Description",
  "category": "Misc",
  "icon": {
    "name": "ActionsIcon",
    "color": "Orange"
  },
  "options": [
    {
      "name": "action",
      "label": "Action",
      "meta": {
        "type": "Action"
      }
    }
  ],
  "yields": "NONE"
}

cli-wiki/functions/exampleFunction/1.0/index.js:

const exampleFunction = async ({ action }) => {
  // e.g.: action === "44af8404efab43d8b825529a4a92aa24"
};

export default exampleFunction;
Example: AuthenticationProfile

cli-wiki/functions/exampleFunction/1.0/function.json:

{
  "label": "Example Function",
  "description": "Description",
  "category": "Misc",
  "icon": {
    "name": "ActionsIcon",
    "color": "Orange"
  },
  "options": [
    {
      "name": "authenticationProfile",
      "label": "Authentication Profile",
      "meta": {
        "type": "AuthenticationProfile",
        "validations": {
          "required": true
        }
      }
    }
  ],
  "yields": "NONE"
}

cli-wiki/functions/exampleFunction/1.0/index.js:

const exampleFunction = async ({ authenticationProfile }) => {
  // e.g.: authenticationProfile === {"authenticationProfile":{"id":"4fd6d526ae36494680ae2ba6a5397482","kind":"usernamePassword"},"password":"1234","username":"John Doe"}
  // e.g.: authenticationProfile === {"authenticationProfile":{"id":"fda8ec953030423ea139e203f6cfcbc0","kind":"customAuthentication"},"userId":1}
};

export default exampleFunction;
Example: Collection

cli-wiki/functions/exampleFunction/1.0/function.json:

{
  "label": "Example Function",
  "description": "Description",
  "category": "Misc",
  "icon": {
    "name": "ActionsIcon",
    "color": "Orange"
  },
  "options": [
    {
      "name": "collection",
      "label": "Collection",
      "meta": {
        "type": "Collection"
      }
    }
  ],
  "yields": "NONE"
}

cli-wiki/functions/exampleFunction/1.0/index.js:

const exampleFunction = async ({ collection: { data: collection } }) => {
  // e.g.: collection === [{id: 1, name: "John Doe"}, {id: 2, name: "Jane Doe"}]
};

export default exampleFunction;
Example: Collection with additional model data

cli-wiki/functions/exampleFunction/1.0/function.json:

{
  "label": "Example Function",
  "description": "Description",
  "category": "Misc",
  "icon": {
    "name": "ActionsIcon",
    "color": "Orange"
  },
  "options": [
    {
      "name": "collection",
      "label": "Collection",
      "meta": {
        "type": "Collection",
        "additional": {
          "model": ["name", { "properties": ["kind"] }]
        }
      }
    }
  ],
  "yields": "NONE"
}

cli-wiki/functions/exampleFunction/1.0/index.js:

const exampleFunction = async ({ collection: { data: collection, model: { name, properties } }) => {
  // e.g.: collection === [{id: 1, name: "John Doe"}, {id: 2, name: "Jane Doe"}]
}

export default exampleFunction;
Example: Record

cli-wiki/functions/exampleFunction/1.0/function.json:

{
  "label": "Example Function",
  "description": "Description",
  "category": "Misc",
  "icon": {
    "name": "ActionsIcon",
    "color": "Orange"
  },
  "options": [
    {
      "name": "record",
      "label": "Record",
      "meta": {
        "type": "Record"
      }
    }
  ],
  "yields": "NONE"
}

cli-wiki/functions/exampleFunction/1.0/index.js:

const exampleFunction = async ({
  selectedRecord: {
    data: { id },
  },
}) => {};

export default exampleFunction;
Example: Record with additional model data

cli-wiki/functions/exampleFunction/1.0/function.json:

{
  "label": "Example Function",
  "description": "Description",
  "category": "Misc",
  "icon": {
    "name": "ActionsIcon",
    "color": "Orange"
  },
  "options": [
    {
      "name": "record",
      "label": "Record",
      "meta": {
        "type": "Record",
        "additional": {
          "model": ["name", { "properties": ["kind"] }]
        }
      }
    }
  ],
  "yields": "NONE"
}

cli-wiki/functions/exampleFunction/1.0/index.js:

const exampleFunction = async ({
  selectedRecord: {
    data: { id },
    model: { name: modelName, properties },
  },
}) => {};

export default exampleFunction;
Example: Value

cli-wiki/functions/exampleFunction/1.0/function.json:

{
  "label": "Example Function",
  "description": "Description",
  "category": "Misc",
  "icon": {
    "name": "ActionsIcon",
    "color": "Orange"
  },
  "options": [
    {
      "name": "anyValue",
      "label": "Value",
      "meta": {
        "type": "Value",
        "allowedKinds": []
      }
    }
  ],
  "yields": "NONE"
}

cli-wiki/functions/exampleFunction/1.0/index.js:

const exampleFunction = async ({ anyValue }) => {};

export default exampleFunction;
Example: Text

cli-wiki/functions/exampleFunction/1.0/function.json:

{
  "label": "Example Function",
  "description": "Description",
  "category": "Misc",
  "icon": {
    "name": "ActionsIcon",
    "color": "Orange"
  },
  "options": [
    {
      "name": "firstName",
      "label": "Firstname",
      "meta": {
        "type": "Text",
        "default": "John"
      }
    }
  ],
  "yields": "NONE"
}

cli-wiki/functions/exampleFunction/1.0/index.js:

const exampleFunction = async ({ firstName }) => {
  // e.g.: firstName === "Betty"
};

export default exampleFunction;
Example: Number

cli-wiki/functions/exampleFunction/1.0/function.json:

{
  "label": "Example Function",
  "description": "Description",
  "category": "Misc",
  "icon": {
    "name": "ActionsIcon",
    "color": "Orange"
  },
  "options": [
    {
      "name": "age",
      "label": "Age",
      "meta": {
        "type": "Number",
        "default": 18
      }
    }
  ],
  "yields": "NONE"
}

cli-wiki/functions/exampleFunction/1.0/index.js:

const exampleFunction = async ({ age }) => {
  // e.g.: age >= 18
};

export default exampleFunction;
Example: Boolean

cli-wiki/functions/exampleFunction/1.0/function.json:

{
  "label": "Example Function",
  "description": "Description",
  "category": "Misc",
  "icon": {
    "name": "ActionsIcon",
    "color": "Orange"
  },
  "options": [
    {
      "name": "adult",
      "label": "Adult",
      "meta": {
        "type": "Boolean",
        "default": true
      }
    }
  ],
  "yields": "NONE"
}

cli-wiki/functions/exampleFunction/1.0/index.js:

const exampleFunction = async ({ adult }) => {
  // e.g.: adult === true
};

export default exampleFunction;
Example: MultilineText

cli-wiki/functions/exampleFunction/1.0/function.json:

{
  "label": "Example Function",
  "description": "Description",
  "category": "Misc",
  "icon": {
    "name": "ActionsIcon",
    "color": "Orange"
  },
  "options": [
    {
      "name": "info",
      "label": "Info",
      "meta": {
        "type": "MultilineText"
      }
    }
  ],
  "yields": "NONE"
}

cli-wiki/functions/exampleFunction/1.0/index.js:

const exampleFunction = async ({ info }) => {
  // e.g.: info >= "Information text"
};

export default exampleFunction;
Example: Select

cli-wiki/functions/exampleFunction/1.0/function.json:

{
  "label": "Example Function",
  "description": "Description",
  "category": "Misc",
  "icon": {
    "name": "ActionsIcon",
    "color": "Orange"
  },
  "options": [
    {
      "name": "language",
      "label": "Language",
      "meta": {
        "type": "Select",
        "default": "EN",
        "values": [
          { "label": "Dutch", "value": "NL" },
          { "label": "English", "value": "EN" },
          { "label": "German", "value": "DE" }
        ]
      }
    }
  ],
  "yields": "NONE"
}

cli-wiki/functions/exampleFunction/1.0/index.js:

const exampleFunction = async ({ language }) => {
  // e.g.: language === "NL"
};

export default exampleFunction;
Example: Model

cli-wiki/functions/exampleFunction/1.0/function.json:

{
  "label": "Example Function",
  "description": "Description",
  "category": "Misc",
  "icon": {
    "name": "ActionsIcon",
    "color": "Orange"
  },
  "options": [
    {
      "name": "model",
      "label": "Model",
      "meta": {
        "type": "Model"
      }
    }
  ],
  "yields": "NONE"
}

cli-wiki/functions/exampleFunction/1.0/index.js:

const exampleFunction = async ({ model }) => {
  // e.g.: model === "44af8404efab43d8b825529a4a92aa24"
};

export default exampleFunction;
Example: Property

cli-wiki/functions/exampleFunction/1.0/function.json:

{
  "label": "Example Function",
  "description": "Description",
  "category": "Misc",
  "icon": {
    "name": "ActionsIcon",
    "color": "Orange"
  },
  "options": [
    {
      "meta": {
        "allowedKinds": ["FILE", "IMAGE"],
        "type": "Property",
        "model": "model",
        "validations": {
          "required": true
        }
      },
      "configuration": {
        "dependsOn": [
          {
            "option": "model",
            "action": "CLEAR"
          }
        ]
      },
      "name": "property",
      "label": "Property"
    }
  ],
  "yields": "NONE"
}

cli-wiki/functions/exampleFunction/1.0/index.js:

const exampleFunction = async ({ property: [{ name: propertyName }] }) => {
  // e.g.: propertyName === "file"
};

export default exampleFunction;
Example: PropertyMap

cli-wiki/functions/exampleFunction/1.0/function.json:

{
  "label": "Example Function",
  "description": "Description",
  "category": "Misc",
  "icon": {
    "name": "ActionsIcon",
    "color": "Orange"
  },
  "options": [
    {
      "name": "selectedModel",
      "label": "Model",
      "meta": {
        "type": "Model"
      }
    },
    {
      "name": "propertyMapping",
      "label": "Assign",
      "meta": {
        "type": "PropertyMap",
        "model": "selectedModel"
      }
    }
  ],
  "yields": "NONE"
}

cli-wiki/functions/exampleFunction/1.0/index.js:

const exampleFunction = async ({ selectedModel, propertyMapping }) => {
  // e.g.: selectedModel === "44af8404efab43d8b825529a4a92aa24"
  // e.g.: propertyMapping === [{key: {name: "firstName"}, value: "Betty"}]
};

export default exampleFunction;

Note: The PropertyMap requires you to set a "model" key, where the value refers to a Model option. In this case the "selectedModel" in the "Assign" option refers to the "Model" option named "selectedModel".

Example: Map

cli-wiki/functions/exampleFunction/1.0/function.json:

{
  "label": "Example Function",
  "description": "Description",
  "category": "Misc",
  "icon": {
    "name": "ActionsIcon",
    "color": "Orange"
  },
  "options": [
    {
      "name": "headers",
      "label": "Headers",
      "meta": {
        "type": "Map"
      }
    }
  ],
  "yields": "NONE"
}

cli-wiki/functions/exampleFunction/1.0/index.js:

const exampleFunction = async ({ headers }) => {
  // e.g.: headers === [{"key":"Betty","value":"Blocks"}]
};

export default exampleFunction;
Example: InputVariableMap

cli-wiki/functions/exampleFunction/1.0/function.json:

{
  "label": "Example Function",
  "description": "Description",
  "category": "Misc",
  "icon": {
    "name": "ActionsIcon",
    "color": "Orange"
  },
  "options": [
    {
      "name": "action",
      "label": "Action",
      "meta": {
        "type": "Action"
      }
    },
    {
      "name": "input",
      "label": "Input Variables",
      "meta": {
        "type": "InputVariableMap",
        "action": "action"
      }
    }
  ],
  "yields": "NONE"
}

cli-wiki/functions/exampleFunction/1.0/index.js:

const exampleFunction = async ({ action, input }) => {
  // e.g.: action === "44af8404efab43d8b825529a4a92aa24"
  // e.g.: input === [{key: {name: "firstName"}, value: "Betty"}]
};

export default exampleFunction;

Note: The InputVariableMap requires you to set an "action" key, where the value refers to an Action option. In this case, the "action" in the "InputVariableMap" option refers to the "Action" option named "action".

Output

Example: Text

cli-wiki/functions/exampleFunction/1.0/function.json:

{
  "label": "Example Function",
  "description": "Description",
  "category": "Misc",
  "icon": {
    "name": "ActionsIcon",
    "color": "Orange"
  },
  "options": [
    {
      "name": "result",
      "label": "Result",
      "meta": {
        "type": "Output",
        "output": {
          "type": "Text"
        }
      }
    }
  ],
  "yields": "NONE"
}

cli-wiki/functions/exampleFunction/1.0/index.js:

const exampleFunction = async () => {
  return {
    result: "Hello World!",
  };
};

export default exampleFunction;
Example: Record

cli-wiki/functions/exampleFunction/1.0/function.json:

{
  "label": "Example Function",
  "description": "Description",
  "category": "Misc",
  "icon": {
    "name": "ActionsIcon",
    "color": "Orange"
  },
  "options": [
    {
      "name": "selectedModel",
      "label": "Model",
      "meta": {
        "type": "Model"
      }
    },
    {
      "name": "result",
      "label": "Result",
      "meta": {
        "type": "Output",
        "output": {
          "type": "Record",
          "model": "selectedModel"
        }
      }
    }
  ],
  "yields": "NONE"
}

cli-wiki/functions/exampleFunction/1.0/index.js:

const exampleFunction = async ({ selectedModel }) => {
  return {
    result: "Hello World!",
  };
};

export default exampleFunction;

Note: Output is not passed as an argument to your function. Instead, it's a key you have to set in the return object of your function.

Example: Inherit Inherit will dynamically set the output type based on another input option.

cli-wiki/functions/exampleFunction/1.0/function.json:

{
  "label": "Example Function",
  "description": "Description",
  "category": "Misc",
  "icon": {
    "name": "ActionsIcon",
    "color": "Orange"
  },
  "options": [
    {
      "name": "action",
      "label": "Action",
      "meta": {
        "type": "Action"
      }
    },
    {
      "name": "result",
      "label": "Result",
      "meta": {
        "type": "Output",
        "output": {
          "type": "Inherit",
          "source": "action"
        }
      }
    }
  ],
  "yields": "NONE"
}

cli-wiki/functions/exampleFunction/1.0/index.js:

const exampleFunction = async ({ selectedModel }) => {
  return {
    result: await runAction({ id, input }),
  };
};

export default exampleFunction;

Note: Output is not passed as an argument to your function. Instead, it's a key you have to set in the return object of your function.

Example: Array

cli-wiki/functions/exampleFunction/1.0/function.json:

{
  "label": "Example Function",
  "description": "Description",
  "category": "Misc",
  "icon": {
    "name": "ActionsIcon",
    "color": "Orange"
  },
  "options": [
    {
      "name": "result",
      "label": "Result",
      "meta": {
        "type": "Output",
        "output": {
          "type": "Array",
          "dataType": "STRING"
        }
      }
    }
  ],
  "yields": "NONE"
}

cli-wiki/functions/exampleFunction/1.0/index.js:

const exampleFunction = async () => {
  return {
    result: ["Apple", "Banana", "Orange"],
  };
};

export default exampleFunction;

Note: Output is not passed as an argument to your function. Instead, it's a key you have to set in the return object of your function.

Example: Any Of

cli-wiki/functions/exampleFunction/1.0/function.json:

{
  "label": "Example Function",
  "description": "Description",
  "category": "Misc",
  "icon": {
    "name": "ActionsIcon",
    "color": "Orange"
  },
  "options": [
    {
      "info": "The schema model can be utilized to type the output of this step when it is an object or an array of objects.",
      "meta": {
        "type": "SchemaModel"
      },
      "name": "schemaModel",
      "label": "Schema Model"
    },
    {
      "name": "result",
      "label": "Result",
      "meta": {
        "type": "Output",
        "output": {
          "anyOf": [
            { "type": "Text" },
            { "type": "Object", "schemaModel": "schemaModel" },
            {
              "type": "Array",
              "schemaModel": "schemaModel",
              "dataType": "SCHEMA"
            },
            { "type": "Number" }
          ]
        }
      }
    }
  ],
  "yields": "NONE"
}

cli-wiki/functions/exampleFunction/1.0/index.js:

const exampleFunction = async () => {
  return {
    result: "Hello World!",
  };
};

export default exampleFunction;

Note: You can use this to provide the option to the user of the action step to choose between multiple output types.

Validations

Example: Min/Max

cli-wiki/functions/exampleFunction/1.0/function.json:

{
  "label": "Example Function",
  "description": "Description",
  "category": "Misc",
  "icon": {
    "name": "ActionsIcon",
    "color": "Orange"
  },
  "options": [
    {
      "name": "age",
      "label": "Age",
      "meta": {
        "type": "Number",
        "validations": {
          "min": 18,
          "max": 88
        }
      }
    }
  ],
  "yields": "NONE"
}

cli-wiki/functions/exampleFunction/1.0/index.js:

const exampleFunction = async ({ age }) => {
  // e.g.: age === 65
};

export default exampleFunction;
Example: Required

cli-wiki/functions/exampleFunction/1.0/function.json:

{
  "label": "Example Function",
  "description": "Description",
  "category": "Misc",
  "icon": {
    "name": "ActionsIcon",
    "color": "Orange"
  },
  "options": [
    {
      "name": "model",
      "label": "Model",
      "meta": {
        "type": "Model",
        "validations": {
          "required": true
        }
      }
    }
  ],
  "yields": "NONE"
}

cli-wiki/functions/exampleFunction/1.0/index.js:

const exampleFunction = async ({ model }) => {
  // e.g.: model === {name: "User"}
};

export default exampleFunction;

Yields

The Yields field gives functions the option to execute nested steps within your function. We currently support three different values for this field, namely: NONE, ALL, PATHS

NONE

You can use this if you don't want any steps to be nested within your function. An example of this is the log function.

Example: NONE

cli-wiki/functions/exampleFunction/1.0/function.json:

{
  "label": "Example Function",
  "description": "Description",
  "category": "Misc",
  "icon": {
    "name": "ActionsIcon",
    "color": "Orange"
  },
  "options": [],
  "yields": "NONE"
}

cli-wiki/functions/exampleFunction/1.0/index.js:

const exampleFunction = async () => {};

export default exampleFunction;

Yields all

ALL

You can use this if you want to execute a set of steps nested within your function. Your function implementation is responsible for executing this set of steps. An example of this is the loop function.

Example: ALL

cli-wiki/functions/exampleFunction/1.0/function.json:

{
  "description": "Loops through a given collection.",
  "label": "Loop",
  "category": "FLOW",
  "icon": {
    "name": "LoopIcon",
    "color": "Blue"
  },
  "options": [
    {
      "meta": {
        "type": "Collection",
        "validations": {
          "required": true
        }
      },
      "name": "collection",
      "label": "Collection",
      "info": "The collection you want to loop through."
    },
    {
      "meta": {
        "type": "Output",
        "output": {
          "type": "Record",
          "model": "collection",
          "scoped": true
        },
        "validations": {
          "required": true
        }
      },
      "name": "iterator",
      "label": "Iterator name",
      "info": "Iterator info."
    },
    {
      "meta": {
        "type": "Output",
        "output": {
          "type": "Number",
          "scoped": true
        }
      },
      "name": "index",
      "label": "Index",
      "info": "Index info."
    }
  ],
  "yields": "ALL"
}

cli-wiki/functions/exampleFunction/1.0/index.js:

const exampleFunction = async ({ collection: { data: collection } }, steps) => {
  for (let index = 0; index < collection.length; index += 1) {
    // steps contains all steps nested within the loop.
    // Which all have "iterator" and "index" as available variables.
    await steps({ iterator: collection[index], index });
  }
  return {};
};

export default exampleFunction;

Yields all

PATHS

You can use this if you want to execute sets of steps based on whether one or more conditions are met. Your function implementation is reponsible for deciding which sets of steps, if any, to execute. An example of this is the condition function. Which executes the first set of steps for which the condition is truthy.

Example: PATHS

cli-wiki/functions/exampleFunction/1.0/function.json:

{
  "label": "Example Function",
  "description": "Description",
  "category": "Flow",
  "icon": {
    "name": "ConditionIcon",
    "color": "Yellow"
  },
  "paths": {
    "min": 1,
    "max": 1,
    "filterOption": {
      "meta": {
        "type": "Value",
        "allowedKinds": ["BOOLEAN"],
        "validations": {
          "required": true
        }
      },
      "name": "value",
      "label": "Value",
      "info": "If this value is evaluated truthy the child steps will be executed."
    },
    "values": [
      {
        "label": "True"
      }
    ]
  },
  "yields": "PATHS"
}

cli-wiki/functions/exampleFunction/1.0/index.js:

const exampleFunction = async (_, paths) => {
  await paths.forEach(async ({ value, steps }, halt) => {
    if (value) {
      // The steps function contains all steps for a single path.
      await steps();
      // Be sure to call the halt function if only one path should be evaluated.
      halt();
    }
  });
};

export default exampleFunction;

Yields all


Advanced

You can mark specific options with advanced true. This will hide your options by default and those can be found under an advanced section. This option is optional.

{
  "meta": {
    "type": "Boolean"
  },
  "advanced": true,
  "name": "advancedOption",
  "label": "Advanced Option",
  "info": "This option will be rendered in the advanced options section"
}

Icons

Note: As of the 25th of October, 2022 we have changed the JSON schema requirement of the icon field from a string to an object.

You can provide your action functions with an icon and color as follows:

{
  "name": "ActionsIcon",
  "color": "Orange"
}

The available icons can be found here and the available colors are:

  • Yellow
  • Green
  • Pink
  • Orange
  • Purple
  • Blue
  • Teal
  • Grey
⚠️ **GitHub.com Fallback** ⚠️