Lesson 2: Explore the App Builder App
Within the newly created app, you have seen the .env
file which contains your credentials for running the app. Let's explore further.
Firstly, package.json
is the crucial part of almost every NodeJS project. It contains the list of dependencies, version, reproducible builds, etc.
Then ext.config.yaml
in the src/dx-excshell-1/
folder is the cockpit of your App Builder app backend. It lists the declaration of serverless actions including name, source files, runtime kind, default params, annotations, and so on. You can find the grammar of writing manifest here.
Copied to your clipboardoperations:workerProcess:- type: actionimpl: dx-asset-compute-worker-1/workerhooks:post-app-run: adobe-asset-compute devtooltest: adobe-asset-compute test-workeractions: actionsruntimeManifest:packages:dx-asset-compute-worker-1:license: Apache-2.0actions:get-profiles:function: actions/get-profiles/index.jsweb: 'yes'runtime: 'nodejs:18'inputs:LOG_LEVEL: debugtenant: $CAMPAIGN_STANDARD_TENANTapiKey: $SERVICE_API_KEYannotations:require-adobe-auth: truefinal: true
Currently your app only has one action get-profiles
.
- Source code is at
src/dx-excshell-1/actions/get-profiles/index.js
- It is a web action
- The action will be run in the
nodejs:18
runtime container on I/O Runtime - It has some default params such as
LOG_LEVEL
,tenant
,apiKey
, which are automatically available in theparams
object of the action without passing it to the action for every invocation. Thefinal
annotation set astrue
tells that those params are immutable. - Setting the
require-adobe-auth
annotation astrue
enables this action to be protected by Adobe IMS user token in the request header. Without it, the action will return401 Unauthorized
error.
Now let's have a deeper look at the action's source code.
Copied to your clipboard/*** This action gets a list of customer profiles the Adobe Campaign Standard API*/const { Core } = require('@adobe/aio-sdk')const { CampaignStandard } = require('@adobe/aio-sdk')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 = ['apiKey', 'tenant']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)// initialize the sdkconst campaignClient = await CampaignStandard.init(params.tenant, params.apiKey, token)// get profiles from Campaign Standardconst profiles = await campaignClient.getAllProfiles()logger.debug('profiles = ' + JSON.stringify(profiles, null, 2))const response = {statusCode: 200,body: profiles}// 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
What happens here, is that the action exposes a main
function, which accepts a list of params from the client. It checks that required params for using the Campaign Standard SDK are present in this list, including the Authorization
header for authentication against Adobe IMS.
An access token is retrieved to initiate the SDK client instance, which is then used to retrieve the list of customer profiles using the getAllProfiles() function. Finally the profiles are returned to the client. This whole execution is wrapped within a try-catch block, so that errors are handled appropriately.
Next, let's see how the web UI communicates with the backend. All web assets are placed in the src/dx-excshell-1/web-src
folder.
Beside a few auto-generated files that are useful for running your app on Adobe Experience Cloud (ExC) Shell, App.js
is the extension point of your UI.
By default, it contains 3 pages: Home and About are just static pages showing listing reference docs, and ActionsForm lists all available backend actions, allows you to select the action to be invoke, and once you click on the "invoke" button, it shows the invocation results in the browser console.
Copied to your clipboard<View gridArea='content' padding='size-200'><Switch><Route exact path='/'><Home></Home></Route><Route path='/actions'><ActionsForm runtime={props.runtime} ims={props.ims} /></Route><Route path='/about'><About></About></Route></Switch></View>