New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@axway/api-builder-sdk

Package Overview
Dependencies
Maintainers
14
Versions
60
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@axway/api-builder-sdk

SDK for implementing custom plugins for API Builder

  • 0.4.0
  • marrakech
  • npm
  • Socket score

Version published
Weekly downloads
400
increased by10.19%
Maintainers
14
Weekly downloads
 
Created
Source

@axway/api-builder-sdk

A plugin SDK for implementing custom flow-nodes for API Builder flows.

Getting started

To get started with API Builder plugin development, use the @axway/api-builder CLI to generate a new plugin project.

npx @axway/api-builder plugin init myplugin
cd api-builder-plugin-myplugin
npm install
npm test

That's it!

You created your first API Builder plugin! The CLI generated an example flow-node called "Hello World" that creates greeting based on provided name. You can use this guide to modify it to create your own custom flow-node. To get you started you can have a look at our collection of examples.

Contributing

You may be interested in contributing your own flow-nodes to the wider API Builder community. While you can choose to keep your flow-nodes private, there are a lot of benefits to making them freely available to the API Builder community as an open source initiative. If you do not want to "own" the source, you can contribute them to api-builder-extras. If you would like your component to appear in the Components list in the UI, we would be happy to review your component and add it to the list. You can email the API Builder team at API.Builder.Team@axway.com.

Using the plugin

The API Builder plugin is an npm module. To use the plugin, you must install the plugin as a dependency of an existing API Builder project. If you do not have a project, refer to the API Builder Getting Started Guide. There are several ways to install a plugin as a dependency (for a complete list see npm-install):

Managing separate modules as dependencies requires a basic understanding of npm that is not covered by this guide (see this guide for more information).

Install a plugin from npm

In order to install a plugin from npm as a dependency, it must first be published to npm (see npm-publish). Run the npm install command to install the plugin as a dependency of an existing API Builder project. This is the best way to manage plugin dependencies.

cd my-existing-api-builder-project
npm install api-builder-plugin-myplugin
npm start

Install a plugin from a relative directory

Assuming your projects all share the same root folder, you can install the plugin directly from source. Note that this is going to create a copy your plugin in the node_modules directory. So, if you modify your plugin, then you will need to run the install command again (you can avoid this by using npm-link).

cd my-existing-api-builder-project
npm install ../api-builder-plugin-myplugin
npm start

Install a plugin from an API Builder project

It is possible to create and manage plugins directly from your API Builder project. It is very similar to installing a plugin from a relative directory, but it has some advantages in that it will share the same source as your project. However, like the relative directory, it still requires that you run npm install, but you will only need to do this once because npm will create a link for you (see npm-link).

cd my-existing-api-builder-project
npm install ./api-builder-plugin-myplugin
npm start

Plugin contents

├───package.json
├───src/
│   ├───actions.js
│   ├───flow-nodes.yml
│   ├───icon.svg
│   ├───index.js
└───test/
    └───test.js
File nameDescription
package.jsonThis is your module package description file. You should modify it to suit your module.
src/actions.jsThis file contains the actual JavaScript implementations of the methods defined in src/flow-nodes.yml. You will add your own method implementations here.
src/flow-nodes.ymlDefines your flow-node. You will modify to add your own flow-node and methods.
src/icon.svgThe icon file that is used in the UI. Supports image formats: bmp, jpeg, png, gif, tiff, or svg.
src/index.jsExports the API Builder plugin. You should not need to modify this file.
test/test.jsA mocha test suite. You should ensure all of your actions are adequately tested.

Creating your own flow-node

The API Builder plugin for flow-nodes is configured using a YAML file called flow-nodes.yaml within each project. The flow-nodes.yaml file defines a structure that determines:

  • The flow-node(s) to export.
  • The method(s) that comprise each flow-node.

To get started, you can modify the example generated by the CLI.

JSON Schema

Flow-nodes utilize JSON schema to describe the acceptable values for various inputs and outputs. For simple parameters, this might just be one of the standard data types, e.g. type: string.

Below are some example schema. Additional examples can be found here.

# The value must be a string.  The standard types are:
# null, boolean, object, array, number, string
type: string
# The value should be a boolean.  The `default` is documentation
# purposes only and has to be handled in code.
type: boolean
default: true
# The value must be string or null
oneOf:
  - type: string
  - type: null
# The value must be a string and either "foo" or "bar"
type: string
enum:
  - foo
  - bar
# The value must be string and match a regex pattern
type: string
pattern: "v[0-9]+"
# The value must be string and is a multiline input format.
# Formats with special UI: multiline, javascript, mustache
type: string
format: multiline
# The value must be an array containing strings.
type: array
items:
  type: string
# The value must be an array containing numbers.
# Limits the minimum number of items of that array to at least 1 and the maximum to 10.
type: array
items:
  type: number
  minItems: 1
  maxItems: 10

flow-node

The flow-nodes key is the top-most element in the flow-nodes.yml file. A flow-node specification begins with a unique key beneath flow-nodes.

A flow-node is really just a container for a number of related functions. Each flow-node will correlate to a single UI element and icon that can be utilized within the API Builder flow editor. You can define multiple flow-nodes in the same plugin project, but generally speaking, it is more advisable to have a single-purpose plugin that defines one flow-node.

flow-nodes:
  myplugin:
    name: My Plugin
    icon: icon.svg
    description: My plugin is awesome.
    category: general
    methods:
      # ...
flow-node attributes

The following table lists the attributes available when defining a flow-node:

KeywordRequiredDescription
namenoA friendly name for your flow-node. This is how it will appear in the UI. Defaults to the flow-node key.
iconnoAn icon file for the UI. Supports formats: bmp, jpeg, png, gif, tiff, or svg. The file must be relative to the flow-nodes.yml file. The height and width of the icon should be equal (e.g. around 80px). Using svg allows the icon to scale cleanly.
descriptionnoA summary of what the flow-node supports.
categorynoThe category to which your flow-node should belong. Defaults to "general".
methodsnoA set of method definitions.

method

A method defines an operation, its input parameters, and its outputs. The method is identified by a unique key below the flow-node methods attribute.

  • Methods are sorted by name in the UI flow-node configuration panel.
  • There is no limit to the number of methods.
  • The method key correlates to an action in the actions.js file. If you rename the method in flow-nodes.yml, you should also rename it in actions.js.
methods:
  getSomething:
    name: Gets something
    description: Gets something from somewhere
    parameters:
      # ...
    outputs:
      # ...

method attributes

The following table lists the attributes available when defining a method.

KeywordRequiredDescription
namenoA friendly name for your method. This is how it will appear in the UI. Defaults to the method key.
descriptionyesA summary of the method.
parametersnoA set of unique parameter definitions.
authorizationsnoA set of unique authorization definitions.
outputsnoA set of unique output definitions.

parameter

A parameter defines an input to the method's action function. The parameter is identified by a unique key below the method's parameters attribute.

The parameter key is used when writing the flow-node action. Typically, the parameter key should be simple property identifier (i.e. A-Z characters), otherwise it will be difficult to use it.

  • There is no limit to the number of method parameters that can be defined.
  • In the flow-node configuration panel in the UI, parameters are sorted first by ungrouped parameters (i.e. by parameters that do not define a group), then alphabetically by parameter group.
  • Within each parameter group, parameters are sorted by required parameters first (required: true), then alphabetically by parameter key.
parameters:
  username:
    name: Username
    description: The user name.
    required: true
    initialType: string
    schema:
      type: string
parameter attributes
KeywordRequiredDescription
descriptionnoA description of the parameter.
requirednoSpecifies that the parameter is required. Defaults to true.
initialTypenoThe initial type to display by default in the UI flow-node configuration panel for this parameter. Allowed values are: object, array, string, selector, null, boolean and number. The default is selector.
groupnoA group name to which the parameter belongs, e.g. "Advanced". By default, all parameters are ungrouped. The group name, "Authorizations" is reserved for future use.
multilineWrappernoDefines the before and after text that surrounds the user-provided parameter value in the UI text editor that gives context (e.g. that the user is defining a function) and prevents users from editing the before and after parts.
schemayesA JSON schema that describes the acceptable value for the input parameter.
parameter multilineWrapper options

The multilineWrapper parameter option provides user-context in the UI when editing the parameter value. It gives context (e.g. that the user is defining a function), and prevents the users from editing the before and after part of the wrapper. A complete wrapper should use newlines for the best effect. The before text would trail with a newline, and the after text would lead with a newline. For example, to achieve an array input so that the user does not have to write the leading "[" or trailing "]":

options:
  multilineWrapper:
    before: "[\n"
    after: "\n]"

When defining a multilineWrapper parameter option, the following table lists the attributes that are available:

KeywordRequiredDescription
beforenoThe leading text. The text should trail with a newline.
afternoThe trailing text. The text should lead with a newline.

The result will be a UI where the leading before and trailing after will not be editable by the user, but provides necessary context while editing. For example:

[
...
]

authorization

An authorization defines authorization parameter to be used for the method's action function. The authorization is identified by a unique key below the method's authorizations attribute.

The authorization parameter key is used when writing the flow-node action. Typically, the authorization parameter key should be simple property identifier (i.e. A-Z characters), otherwise it will be difficult to use it. There is no limit to the number of authorizations that can be defined.

authorizations:
  oauth2:
    description: oAuth2 authorization.
    required: true
    schema:
      type: object
authorization attributes
KeywordRequiredDescription
descriptionnoA description of the authorization.
requirednoSpecifies that the authorization is required. Defaults to true.
schemayesA JSON schema that describes the acceptable value for the authorization.

output

An output defines a possible way that a method can be resolved. The output is identified by a unique key below the method's outputs attribute.

An output can be thought of as an event that is triggered when the flow-node resolves at runtime. Typically, successful resolutions should be listed first, e.g. next, and error resolutions should be listed last, e.g. error.

  • Outputs are sorted by name in the UI flow-node configuration panel.
  • There is no limit to the number of method outputs.
  • Outputs are bound to callback functions and are invoked from actions at runtime.
  • The value returned from the callback function is stored in the context at runtime.
  • For consistency, you should use Error in your error outputs.
outputs:
  next:
    name: Next
    description: Success
    context: $.value
  error:
    name: Error
    description: Something happened
    context: $.error
output attributes

The following table lists the attributes available when defining an output:

KeywordRequiredDescription
namenoDefaults to the output key. A friendly name for your output. This is how it will appear in the UI. Defaults to the output key.
descriptionnoDescribes the output value.
contextyesA JSON path expression used to update the runtime context. For example, $.value.
schemanoA JSON schema that describes the value for the output parameter.

Actions

An action is a JavaScript function implementation that is defined in the actions.js file. It must be exported with the same key as the flow-node method key defined in the flow-nodes.yaml file.

async function getSomething(req, outputs, options) {
    # ...
}
module.exports = {
    getSomething
};

The first argument, req is a runtime context from the flow engine. The flow engine resolves the all of input parameters that are necessary to invoke the action. If any input parameter fails to resolve, the flow execution will fail, and the action function will not be called. The request parameters can be accessed via req.params. The flow-node input parameters, can be accessed using the same parameter key as was defined in the flow-node method (e.g. req.param.username). In addition, the flow engine will also provide access to credentials via req.authorizations (see API Builder Credentials for more information).

  • Actions are asynchronous and should resolve using an output callback from outputs when the operation completes once.
  • Action functions should be stateless. Do not use globals or maintain state.
  • The action functions should be well written and relatively easy to use from the flow.
function getSomething(req, outputs) {
    if (!req.params.username) {
        return outputs.error(null, 'invalid username');
    }
    return outputs.next(null, { user: true });
}

The second argument, outputs is a set of callback functions explained below.

The third argument, options is all the additional options provided from the flow engine. It provides access to the API Builder logging capabilities. It can be accessed via options.logger and used to log at the desired level(e.g. options.logger.error('...')).

options also provides pluginConfig which is the user-configuration for this plugin provided by the API Builder in getPlugin. This is made available to actions by passing an option of the same name to the SDK constructor: new SDK({ pluginConfig }). This is accessed within the action viaoptions.pluginConfig.

Callback and method outputs

The callback is a function convention for waiting for asynchronous code. You can read more about the callback convention here. The outputs is a set of callback functions that are keyed to the outputs defined in the flow-node method. Below is an example callback for the next output:

outputs.next = function(error, arg)

The first argument, error, instructs the flow engine to abruptly abort the flow. It should be used sparingly. The second argument, arg is the return value for the output callback. At runtime, the value of arg will be assigned using the context that was defined for the method output (e.g. $.value).

  • The callback has an output function for every output defined for the method.
  • The callback must only be called once at runtime, and only after all asyncronous tasks are complete and the action is finished.

Writing unit-tests

The SDK comes a utility to help test your flow-node, MockRuntime.

const { MockRuntime } = require('@axway/api-builder-sdk');

Your plugin exports the getPlugin function in index.js. This will be required in your unit-tests.

const getPlugin = require('../src');

The plugin will be loaded and invoked by the API Builder runtime, so it is necessary to use MockRuntime to emulate this for unit-testing.

const plugin = await MockRuntime.loadPlugin(getPlugin);

The runtime instance has a validate function that ensures the flow-node adheres to the schema.

it('should define valid flownodes', () => {
    // if this is invalid, it will throw and fail
    plugin.validate();
});

Then you can use getFlowNode to obtain a handle to your flow-node and invoke it with various arguments, checking the response as appropriate.

it('should succeed with valid argument', async () => {
    const flowNode = plugin.getFlowNode('myplugin');
    const result = await flowNode.getSomething({ username: 'jbloggs' });
    expect(result.callCount).to.equal(1);
    expect(result.output).to.equal('next');
    expect(result.args).to.equal([ null, { user: true }]);
    expect(result.context).to.deep.equal({ something: { user: true } });
});

In some cases, your flow-node may require credentials in addition to the standard parameters. The mocked action method has an additional argument that is used to provide authorized credentials:

it('should succeed with expected arguments', async () => {
    const flowNode = runtime.getFlowNode('myplugin');
    const params = { name: 'bob' };
    const authorizations = { key: '1234' };
    const result = await flowNode.getSomething(params, authorizations);

    const expected = {
      params: {
        name: 'bob'
      },
      authorizations: {
        key: '1234'
      }
    };

    expect(result.callCount).to.equal(1);
    expect(result.output).to.equal('next');
    expect(result.args).to.deep.equal([ null, expected ]);
    expect(result.context).to.deep.equal({ next: expected });
});

Unit-test API

MockRuntime.loadPlugin(getPlugin)

An async function that mocks the API Builder runtime that is used for testing flow-nodes. Pass it the getPlugin function from index.js. It resolves to a plugin that is suitable for testing.

const plugin = await MockRuntime.loadPlugin(getPlugin);
plugin.validate()

Validates the flow-nodes to ensure it adheres to the schema.

plugin.getFlowNode(name)

Obtains a flow-node instance suitable for testing. The actions.js methods are bound to the object instance as asynchronous functions. For example, if you have an action getSomething:

const flowNode = plugin.getFlowNode('myplugin');
const result = await flowNode.getSomething({ username: 'jbloggs' });
result.callCount

The number of times the output callback was called.

result.args

An array of arguments that was passed into the callback function. The first argument is err and the second argument is the response value.

result.output

If a callback output was called, it is the name of the output that was called, e.g. "next". If the default callback was called, this value is undefined.

result.context

If a callback output was called, it is the name of the output's context that was called. For example, if the output context is defined as "$.value", then the runtime will write the second callback argument arg to "value". If the default callback was called or if the output was not defined with a context, then this value is undefined.

Debugging runtime

To debug the API Builder runtime, you can temporarily add a debugger statement (just remember to remove it after you are done). Depending on how you decided to install the plugin, you may need to run npm install after adding the debugger statement. It is recommended to use npm-link to make this process easier.

function getSomething(req, callback) {
    debugger;
}

Then, you can run npm start with additional arguments that will instruct Node.js to wait for a debugger to attach. In you API Builder project directory, execute:

npm start -- --inspect-brk

Then attach using a JavaScript debugger. We recommend using Chrome. Browse to:

chrome://inspect/#devices

And then click on the link Open dedicated DevTools for Node. Once attached, you can invoke your flow and the debugger should automatically break at your debugger statement.

Debugging unit-tests

To debug unit-tests, the process is much the same as debugging runtime, except that the command to execute is different. In your plugin directory, execute:

npm test -- --inspect-brk

Programmatic API

There is also a API that can be used to programmatically generate flow-nodes.

Changes

0.4.0
  • #6312: breaking change: Removed SDK.clear API.
  • #6312: Remove validation that limited the number of method action arguments to make the SDK more permissive.
  • #6312: The SDK constructor takes an additional option pluginConfig: new SDK({ pluginConfig }).
  • #6312: A pluginConfig property was added to action options. This is the same object as the pluginConfig option provided to the SDK constructor.
0.3.0
  • #6329: breaking change: Simplified MockRuntime interface for loading the plugin. Instead of calling getPlugin directly, a loadPlugin method was added to MockRuntime that calls getPlugin for you. Using this method, you can also pass plugin configuration and runtime options (e.g. logger) into your tests, e.g. await MockRuntime.loadPlugin(getPlugin, pluginConfig, options), which resolves to plugin.
  • #6329: breaking change: MockRuntime.validate moved to plugin.validate.
  • #6329: breaking change: MockRuntime.getFlowNode moved to plugin.getFlowNode.
  • #6329: An appDir property was added to getPlugin options, which is the API Builder's runtime project directory. When run in unit-tests, it is process.cwd but you can override this in MockRuntime.loadPlugin.
  • #6329: A logger property was added to getPlugin options and action options, which is the API Builder's runtime logger. When run in unit-tests, it is stubbed to not do any logging, but you can override this in MockRuntime.loadPlugin.
  • #6313: Added the ability to provide authorization parameters to the mocked action methods via MockRuntime.
0.2.1
  • #5012: Add authorization support to the API Builder SDK.
0.2.0
  • #6238: Add support for async functions as actions.
0.1.2 - 0.1.4
  • #6238: Adding a method will now automatically set empty description if unset.
0.1.1
  • #6174: SDK documentation updates.
0.1.0
  • #4899: Breaking change
  • #4899: Renamed module from axway-flow-sdk to @axway/api-builder-sdk
  • #4899: Removed bin/axway-flow and integrated it with @axway/api-builder CLI
  • #4899: Removed mocknode and validate from axway-flow-sdk
  • #4899: Added MockRuntime with mock and validate functions
  • #4899: Unit-testing flow-nodes must be done through MockRuntime
3.4.2
  • #6116: Internal cleanup chore.
3.4.1
  • #6074: Internal CI chore
3.4.0
  • #5924: Added support for string parameters having a format of "mustache".
3.3.0
  • #5892: Added support for defining a type for parameters to display by default in the Flow editor. Previously parameters always started with selector. Now they will consider the type provided using initialType as an option:
.parameter('myToggle', {
  type: 'boolean'
}, {
  initialType: 'boolean'
})
3.2.0
  • #5891: Added alternative way to define parameter options. Instead of false as a third argument to .parameter(), an object can be provided as { required: false }.
  • #5891: Added support for defining wrapper text for multiline and javascript format parameters. This wrapper text will be displayed in the parameter editor but will not be part of the value when saved in the flow. This is useful for when context or comments are needed.
3.1.11
  • #5923: Fix issue where README.md was not published.
  • #5923: Fix issue where README.md was generated with hardcoded docs.
3.1.10
  • #5914: Internal change to re-introduce readme generation from JSDoc.
3.1.9
  • #5887: Fix issue where the axway-flow -n command would throw an error
3.1.8
  • #5895: Fix issue where new Flow-Node projects would not get generated with a test directory.
3.1.7
  • #5711: Internal cleanup of npm scripts.
3.1.6
  • #5708: Internal changes removing readme autogeneration.
3.1.5
  • #5708: Internal changes to mocha configuration.
3.1.4
  • #5709: Internal changes to update eslint rules.
3.1.3
  • #5707: Internal cleanup to code coverage during build process.
3.1.2
  • #5742: Internal change to replace dot dependency with ejs when generating new flow-node plugins.
3.1.0
  • #5600: Support schema references by disabling validation when building flow-nodes.
3.0.0
  • #5436: Breaking Change: Minimum supported version of API Builder is now Jakarta
  • #5436: Moves advanced HTTP options into a new group, "Advanced HTTP Options"
2.0.9
  • #4757: Changed SCM repository and associated internal cleanup.

License

This code is proprietary, closed source software licensed to you by Axway. All Rights Reserved. You may not modify Axway’s code without express written permission of Axway. You are licensed to use and distribute your services developed with the use of this software and dependencies, including distributing reasonable and appropriate portions of the Axway code and dependencies. Except as set forth above, this code MUST not be copied or otherwise redistributed without express written permission of Axway. This module is licensed as part of the Axway Platform and governed under the terms of the Axway license agreement (General Conditions) located here: https://support.axway.com/en/auth/general-conditions; EXCEPT THAT IF YOU RECEIVED A FREE SUBSCRIPTION, LICENSE, OR SUPPORT SUBSCRIPTION FOR THIS CODE, NOTWITHSTANDING THE LANGUAGE OF THE GENERAL CONDITIONS, AXWAY HEREBY DISCLAIMS ALL SUPPORT AND MAINTENANCE OBLIGATIONS, AS WELL AS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO IMPLIED INFRINGEMENT WARRANTIES, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, AND YOU ACCEPT THE PRODUCT AS-IS AND WITH ALL FAULTS, SOLELY AT YOUR OWN RISK. Your right to use this software is strictly limited to the term (if any) of the license or subscription originally granted to you.

Keywords

FAQs

Package last updated on 21 Apr 2020

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc