Lesson 2: Writing a Serverless Action
There are many npm packages available for displaying barcodea, but some don't play well in serverless environments. For this Code Lab, we'll use bwip-js to render a code128 barcode.
Barcode action
First, install the dependency with:
Copied to your clipboardnpm i bwip-js --save
Then import the dependency into your action:
Copied to your clipboardconst bwipjs = require('bwip-js');
Now we can use the library and generate a barcode buffer in the exported main function:
Copied to your clipboardconst buffer = await bwipjs.toBuffer({bcid: 'code128',text: params.value,scale: 3,height: 10,includetext: false,});
Notice that we defined a value
parameter to be passed to the barcode generator configuration.
This is the actual data the barcode will encode.
Then we can return the image representation of the buffer with:
Copied to your clipboardreturn {headers: { 'Content-Type': 'image/png' },statusCode: 200,body: buffer.toString('base64')};
Finally we can add checks to verify the requested value
parameter, logging, and appropriate error handling to obtain this action:
Copied to your clipboardconst { Core } = require('@adobe/aio-sdk');const { errorResponse, stringParameters, checkMissingRequestInputs } = require('../utils');const bwipjs = require('bwip-js');// main function that will be executed by Adobe I/O Runtimeasync function main (params) {// create a Loggerconst logger = Core.Logger('main', { level: params.LOG_LEVEL || 'info' });try {// 'info' is the default level if not setlogger.info('Calling the main action');// log parameters, only if params.LOG_LEVEL === 'debug'logger.debug(stringParameters(params));// check for missing request input parameters and headersconst requiredParams = ['value'];const errorMessage = checkMissingRequestInputs(params, requiredParams);if (errorMessage) {// return and log client errorsreturn errorResponse(400, errorMessage, logger);}const buffer = await bwipjs.toBuffer({bcid: 'code128',text: params.value,scale: 3,height: 10,includetext: false,backgroundcolor: 'ffffff'});return {headers: { 'Content-Type': 'image/png' },statusCode: 200,body: buffer.toString('base64')};} catch (error) {// log any server errorslogger.error(error);// return with 500return errorResponse(500, error.message, logger);}}exports.main = main;
You can run the action locally using the CLI with:
Copied to your clipboardaio app run --local
This will:
- Start a local OpenWhisk stack on Docker.
- Package and deploy the Runtime action and its dependencies using a built-in webpack configuration.
- Start a local development environment and provide the action url e.g.
http://localhost:3233/api/v1/web/guest/my-barcode-app-0.0.1/barcode
for testing and debugging.
We'll discuss how to debug an App Builder app in a later Code Lab.
Nowadd the value parameter, e.g. ?value=test
, to the url so the action will generate a barcode:
Deploying
You can deploy an App Builder Headless app with aio app run
or aio app deploy
. Either will deploy the actions to Adobe I/O Runtime.
aio app deploy
would have deployed the UI to a CDN, but since we don't have a UI that step is ignored. A separate Code Lab will show how to build an App Builder App with UI.
Make sure to set your Adobe I/O Runtime secrets (namespace and auth) in the .env
file.
Turn off the built-in authentication by setting require-adobe-auth: false
in the manifest.yml
.
The security topic will be covered in a separate Code Lab.
Hitting deploy with the CLI will output the deployed action url:
Congratulations! Your first App Builder Headless App is live.
We can test whether the passed value is correctly rendered as a barcode using one of the many barcode readers available.