Lesson 1: Bootstrap a Headless App Builder App
In order to create your barcode application, use the following command:
Copied to your clipboardaio app init my-barcode-app --no-extensions
We select the org, project and workspace for our app, and then be presented with a few options what you want your app to include (Serverless Actions, Web UI, CI/CD pipeline, I/O Events). Since we are building a headless app, we're only interested in using Actions: Deploy Runtime actions
.
The second question, the CLI asks us which experience cloud or experience platform apps you want to extend or build. In this case, we're going to choose Generic
.
The third question, we'll specify the action name barcode
.
What's happening here, from the command line a developer project is created that includes everything from the serverless actions, configuration files, tests etc.
We didn't include the UI setup nor the CI/CD pipeline nor I/O Events. These topics will be covered in other codelabs.
For our barcode app, we'll start by modifying the following files:
app.config.yaml which contains all defined actions with their default parameters:
Copied to your clipboardapplication:actions: actionsweb: web-srcruntimeManifest:packages:my-app:license: Apache-2.0actions:generic:function: actions/generic/index.jsweb: 'yes'runtime: 'nodejs:14'inputs:LOG_LEVEL: debugannotations:require-adobe-auth: truefinal: true
package.json holds your app name, version and all dependencies that will be bundled when deploying the barcode action:
Copied to your clipboard{"name": "my-barcode-app","version": "0.0.1","dependencies": {"@adobe/aio-sdk": "^2.1.0","node-fetch": "^2.6.0"},"devDependencies": {"jest": "^24.9.0","@adobe/wskdebug": "^1.1.0"},"scripts": {"test": "jest","e2e": "jest --collectCoverage=false --testRegex ./e2e"}}
.env should not be committed as this is where you'll store your Adobe I/O Runtime secrets (namespace and auth):
Copied to your clipboard# Specify your secrets here# This file should not be committed to source control## please provide your Adobe I/O Runtime credentials# AIO_RUNTIME_AUTH=# AIO_RUNTIME_NAMESPACE=
actions/barcode/index.js is the source code of your barcode action:
Copied to your clipboard/** <license header>*//*** This is a sample action showcasing how to access an external API*/const { Core } = require('@adobe/aio-sdk')const fetch = require('node-fetch')const { errorResponse, getBearerToken, stringParameters, checkMissingRequestInputs } = require('../utils')// 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 = [/* add required params */]const errorMessage = checkMissingRequestInputs(params, requiredParams, ['Authorization'])if (errorMessage) {// return and log client errorsreturn errorResponse(400, errorMessage, logger)}// extract the user Bearer token from the input request parametersconst token = getBearerToken(params)// replace this with the api you want to accessconst apiEndpoint = 'https://adobeioruntime.net/api/v1/api-docs'// fetch content from external api endpointconst res = await fetch(apiEndpoint)if (!res.ok) {throw new Error('request to ' + apiEndpoint + ' failed with status code ' + res.status)}const content = await res.json()logger.debug('fetch content = ' + JSON.stringify(content, null, 2))const response = {statusCode: 200,body: content}// log the response status codelogger.info(`${response.statusCode}: successful request`)return response} catch (error) {// log any server errorslogger.error(error)// return with 500return errorResponse(500, 'server error', logger)}}exports.main = main