Skip to content

Instantly share code, notes, and snippets.

@charles-jaynes
Forked from composer2/README.md
Last active December 18, 2018 21:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save charles-jaynes/52b539d37b79c548a23935782f6071c3 to your computer and use it in GitHub Desktop.
Save charles-jaynes/52b539d37b79c548a23935782f6071c3 to your computer and use it in GitHub Desktop.
Axway Flow SDK

Creating flow-nodes for API Builder Standalone with Axway Flow SDK

API Builder is a tool that enables developers to rapidly create APIs and microservices with a low-code/no-code approach. API Builder achieves this by enabling you to develop your business logic using Flows. A Flow allows you to orchestrate your business logic visually as a graph of connected flow-nodes.

The Axway Flow SDK (axway-flow-sdk) is a standalone utility that enables the creation of custom flow-nodes for API Builder flows. By offering the Axway Flow SDK as a standalone utility, new flow-nodes can be developed and consumed in API Builder.

In this post, we'll look at features available in the Axway Flow SDK and how easy it is to create a new flow-node. For this example, we'll create an MD5 flow-node and integrate it into an API Builder service.

Installing the Axway Flow SDK

npm install -g axway-flow-sdk

Using the Axway Flow SDK

The following generates a new flow-node starter project in the current directory. You can customize the starter project to meet your requirements.

axway-flow -n <node name>
cd <node name>
npm install
npm run build

The generated starter project name is prefixed with the required api-builder-plugin-fn- prefix.

The starter project is heavily commented to simplify the process of customizing it. It also comes with the eslint configuration and the mocha unit tests incorporated to help you ensure the quality of your custom flow-node.

Sample MD5 flow-node

As an example of how to write a flow-node, we will examine creating a flow-node that allows the hashing of strings from within the flow.

Create the project

axway-flow -n md5 -d 'MD5 hashing of strings.'
cd api-builder-plugin-fn-md5
npm install
npm install md5
npm run build

Customize the flow-node definition in the index.js file

const sdk = require('axway-flow-sdk');
const action = require('./action');

function getFlowNodes() {
	const flownodes = sdk.init(module);

	// The unique name of your flow-node.  You can define multiple flow-nodes in this
	// file, but one is typical.
	flownodes.add('md5', {
		name: 'Md5',
		// file support for: svg, png, gif, bmp, jpg, and tiff
		icon: 'icon.svg',
		description: 'MD5 hashing of strings.'
	})
		// Add a method to your flow-node.
		.method('md5', {
			name: 'MD5',
			description: 'Perform a MD5 hash.'
		})
		// Add parameter(s) to your method.
		.parameter('plaintext', {
			description: 'The plain text to hash.',
			type: 'string'
		}, true)
		// Once all parameters for the method are defined, add output(s) to your method.
		.output('next', {
			name: 'Next',
			description: 'The hashed value',
			context: '$.hash',
			schema: {
				type: 'string'
			}
		})
		.action(action);

	return Promise.resolve(flownodes);
}

exports = module.exports = getFlowNodes;

To explain what occurs in the index.js file, we will break the file down piece by piece.

Describe the flow-node, name, description, category, and icon:

.add('md5', {
	name: 'Md5',
	// file support for: svg, png, gif, bmp, jpg, and tiff
	icon: 'icon.svg',
	description: 'MD5 hashing of strings.'
})

The name is the text that is displayed in the Flow Editor. The default icon is a placeholder (a star) that should be replaced with a graphic that represents the action of the flow-node. The icon is displayed at 28 pixels x 28 pixels. The category is the section in the Flow Editor tool panel where the flow-node is contained.

To download and use an icon that represents a hash, click Hash icon for MD5 flow-node.

Add a method to the flow-node and describe its parameters:

.method('md5', {
	name: 'MD5',
	description: 'Perform a MD5 hash.'
})

A method called md5, that is displayed in the Flow Editor as MD5, was added. The md5 method has a single parameter. If there was more than one parameter, we would repeat the .parameter(name, schema) block. The second value in the parameter method is a JSON schema that describes the parameter type.

Describe the possible outputs from the method:

.output('next', {
	name: 'Next',
	description: 'The hashed value',
	context: '$.hash',
	schema: {
		type: 'string'
	}
})

The outputs section defines the possible outcomes of the flow-node. In this simple case there is just one output; however, flow-nodes can have multiple outputs with different return types. For example, this flow-node could have added an error output to indicate that encoding failed.

Define the implementation:

	.action(action);

The action() expects a function that will be passed the request details parameter and a callback object parameter.

Customize the flow-node method implementation

To simplify the management of the code, the starter project puts the implementation of the methods in the action.js file. There isn't a requirement to follow this pattern, you can structure your project how best suits your needs.

const md5 = require('md5');
exports = module.exports = function (req, cb) {
	const param = req.params.plaintext;
	if (!param) {
		// invoking the callback with an error will terminate the flow.
		return cb('invalid argument');
	}
	cb.next(null, md5(param));
};

This is a simple scenario, but it highlights the main features. The parameters for the flow-node method are accessed under the req.params parameter (defined in the index.js file). In this example, the parameter for the hash method is defined as plaintext:

.parameter('plaintext', {
	description: 'The plain text to hash.',
	type: 'string'
}, true)

The logic checks that the parameter is set. If plaintext is not set, it fires a generic error callback.

return cb('invalid argument');

Unit test your flow-node

The starter project includes automatically generated unit tests in the ./test directory of your project. The tests are for example purposes and will need to be customized to your specific use case. The SDK provides a mocknode that allows for mock invocations of your flow-node methods.

Use mocknode to test error callback existence - valid argument

This example uses mocha to check that the specification is defined well enough to pass the plaintext argument to the method. It also mocks the callback using the defined output of the specification and ensures that the method invokes the correct callback.

const md5 = require('md5');

it('[TEST-3] should succeed', () => {
const hashed = md5('some string');
    return mocknode(flownodes).node('md5')
        .invoke('md5', { plaintext: 'some string' })
        .then((data) => {
            expect(data).to.deep.equal({
                    next: [ null, hashed ]
            });
        });
});

Use mocknode to test error callback existence - invalid argument

This example is similar to the previous example, except that the method will invoke a cb('invalid argument') when given an undefined parameter.

it('[TEST-4] should fail to with invalid argument', () => {
    return mocknode(flownodes).node('md5')
        .invoke('md5', { plaintext: null })
        .then((data) => {
            expect(data).to.deep.equal(
            [ 'invalid argument' ]
        );
        });
});

Test that validity of the flow-node specification

The Axway Flow SDK tries to prevent the creation of invalid flow-node specifications, but there are some edge cases where it may be possible to generate a flow-node specification that is invalid at runtime. To detect this, the generated specification should be validated as part of your unit tests.

it('[TEST-5] should define valid node specs', () => {
    expect(validate(flownodes)).to.not.throw;
});

Installing the flow-node in API Builder service

While unit testing is important, it is also necessary to be able to install the custom flow-node into your local API Builder service for testing.

Create an installable flow-node

This can be achieved by packing the module locally:

cd api-builder-plugin-fn-md5
npm install
npm run build
npm pack

This will create a TGZ archive (api-builder-plugin-fn-md5-1.0.0.tgz) that can then be installed into your Arrow application.

Create an API Builder service

npx @axway/api-builder init md5-demo
cd md5-demo
npm install --no-optional
npm install <path to flow node project>/api-builder-plugin-fn-md5-1.0.0.tgz
npm start

API Builder will now be running and accessible on http://localhost:8080/console.

Use the MD5 flow-node

Navigate to the Greeting API endpoint.

Click on Flow link to navigate to the Flow Editor.

The following displays the completed state of our flow.

The sidebar lists the newly created MD5 flow-node under General. Drag and drop it in the editor and place it between the Check Username flow-node and the Format Greeting flow-node.

In the MD5 flow-node, we have to make one change under parameters.

Use this snippet:

$.params.username

In the Format Greeting flow-node, we have to change the template so we can see our hashed string.

Use this snippet:

{{=it.config.helloworld.salutation}}
{{=it.hash}}

That's all the changes we need to implement our new flow-node. We can now apply the changes and close the editor. Closing the editor will return us to the Greeting API endpoint. In order to test endpoint, we have to expand the endpoint and enter a random username and click Execute. The execute response should appear as follows:

Summary

Creating with Axway Flow SDK is a simple, fast, and easy process. You can create various flow-nodes and unit test them before using them in API Builder service endpoints. This gives you the flexibility to integrate with the endpoints you need to, without having to sacrifice the low-code/no-code experience that API Builder provides.

Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment