Skip to content

Codexpect/app-builder-tutorial

Repository files navigation

Adobe App Builder TypeScript Template

A TypeScript template for Adobe App Builder that demonstrates how to build Adobe Commerce applications with type safety and modern development practices.

Overview

This template provides a TypeScript-based foundation for building Adobe App Builder applications. While the official Adobe Commerce Integration Starter Kit provides comprehensive JavaScript implementations for multi-provider integrations (ERPs, CRMs, PIMs), this template focuses on defining TypeScript configuration that works with Adobe App Builder, along with initial types and utility functions for:

  • Adobe IO Events: Sending events through Adobe IO Events
  • Adobe I/O lib-state: State management utilities
  • Adobe I/O lib-files: File storage utilities
  • Adobe Commerce Client: Works with both PaaS and SaaS Adobe Commerce instances
  • Type Safety: Full TypeScript support with strict type checking

Getting Started

  1. Clone the template:

    git clone <repository-url>
    cd app-builder-typescript-template
  2. Install dependencies:

    npm install
  3. Connect to Adobe App Builder:

    This step will connect your starter kit project to the App Builder project you created earlier. Ensure to select the proper Organization > Project > Workspace with the following commands:

    aio login
    aio console org select
    aio console project select
    aio console workspace select

    Sync your local application with the App Builder project using the following command:

    aio app use
    # Choose the option 'm' (merge)
  4. Configure environment:

    cp env.sample .env
    # Edit .env with your Adobe Commerce credentials
  5. Build the project:

    npm run build

    For development, you can use the watch mode to automatically rebuild on file changes:

    npm run watch
  6. Run tests:

    npm test
  7. Deploy to Adobe App Builder:

    aio app deploy

Project Structure

app-builder-typescript-template/
├── actions-src/                    # TypeScript source code
│   ├── example-1/                 # Example 1: Direct function definition
│   │   └── process/
│   │       ├── index.ts
│   │       └── types/
│   ├── example-2/                 # Example 2: Imported configuration
│   │   ├── action/
│   │   │   ├── index.ts
│   │   │   └── types/
│   │   └── actions.config.yaml
│   ├── logger.ts                  # Logging utilities
│   ├── openwhisk.ts              # OpenWhisk utilities
│   ├── responses.ts               # Response helpers
│   ├── types/                     # TypeScript type definitions
│   ├── utils.ts                   # Utility functions
│   └── utils/                     # Utility modules
│       ├── adobe-commerce/        # Adobe Commerce integration
│       │   ├── adobe-commerce-client.ts
│       │   └── types/
│       ├── io-auth/               # Adobe authentication
│       │   └── adobe-auth.ts
│       ├── io-events/             # Adobe IO Events
│       │   ├── adobe-events-api.ts
│       │   └── naming.ts
│       ├── lib-files/             # File storage utilities
│       │   └── storage-client.ts
│       └── lib-state/             # State management utilities
│           └── state-client.ts
├── actions/                       # Compiled JavaScript (generated)
├── packages/                      # Local packages
│   └── commerce-sdk-auth/         # Adobe Commerce SDK authentication
├── test/                          # Test files
├── app.config.yaml                # Main App Builder configuration
├── package.json                   # Dependencies and scripts
├── tsconfig.json                  # TypeScript configuration
└── eslint.config.mjs             # ESLint configuration

TypeScript Configuration

Source Code Organization

Unlike typical Adobe App Builder projects where source code is directly in the actions/ directory, this template uses a TypeScript workflow:

  • Source code: actions-src/ - Contains all TypeScript files
  • Compiled output: actions/ - Contains compiled JavaScript files (generated by build process)
  • Adobe App Builder: Only uses the actions/ directory for deployment

TypeScript Configuration Files

  • tsconfig.json: Main configuration with CommonJS module system
  • tsconfig.cjs.json: CommonJS-specific configuration
  • tsconfig.es.json: ES modules configuration
  • tsconfig.types.json: Type declaration generation

The build process compiles TypeScript from actions-src/ to JavaScript in actions/, ensuring Adobe App Builder can deploy the compiled code.

Dependencies

Core Dependencies

  • @adobe/aio-sdk: Adobe I/O SDK for App Builder
  • @adobe/aio-lib-state: State management for serverless functions
  • @adobe/aio-lib-ims: Adobe Identity Management System
  • @adobe/commerce-sdk-auth: Adobe Commerce authentication utilities
  • axios: HTTP client for API requests
  • oauth-1.0a: OAuth 1.0a authentication
  • openwhisk: OpenWhisk runtime utilities
  • cloudevents: CloudEvents specification implementation
  • node-fetch: Fetch API for Node.js
  • uuid: UUID generation

Development Dependencies

  • typescript: TypeScript compiler
  • jest: Testing framework
  • eslint: Code linting
  • @typescript-eslint: TypeScript ESLint rules
  • ts-jest: TypeScript support for Jest
  • ts-node: TypeScript execution for Node.js

Configuration Examples

Example 1: Direct Function Definition

In app.config.yaml, functions are defined directly with paths pointing to the compiled actions/ directory:

example-1:
  license: Apache-2.0
  actions:
    process:
      function: actions/example-1/process/index.js # Points to compiled JS
      web: "yes"
      runtime: nodejs:20
      inputs:
        LOG_LEVEL: debug
        COMMERCE_BASE_URL: $COMMERCE_BASE_URL
        # ... other inputs

Example 2: Imported Configuration

For complex configurations, you can import separate config files:

example-2:
  license: Apache-2.0
  actions:
    $include: ./actions-src/example-2/actions.config.yaml # Import from source

In actions-src/example-2/actions.config.yaml:

process:
  function: ../../actions/example-2/action/index.js # Points to compiled JS
  web: "yes"
  runtime: nodejs:20
  inputs:
    LOG_LEVEL: debug
    # ... other inputs

Important: Function paths in configuration files must always point to the actions/ directory (compiled JavaScript), not actions-src/ (TypeScript source).

Adobe Commerce Integration

The template includes a comprehensive Adobe Commerce client that supports:

Authentication Methods

  1. OAuth 1.0a: Traditional Adobe Commerce API authentication
  2. IMS (Identity Management System): Modern Adobe authentication

Usage Example

import { AdobeCommerceClient } from "../utils/adobe-commerce/adobe-commerce-client";

export async function main(params: ProcessFunctionParams): Promise<AppResponse> {
  const storeConfig = {
    storeCode: "us",
    storeUrl: "https://us.example.com",
  };

  const client = AdobeCommerceClient.create(params, storeConfig);

  // Make API calls
  const products = await client.get("/rest/V1/products");

  return actionSuccessResponse("Operation completed");
}

Adobe IO Events Integration

The template includes comprehensive Adobe IO Events support for publishing events:

Event Publishing Example

import { EventCode, ProviderKey, publishEvent } from "../../utils/io-events/adobe-events-api";

export async function main(params: ProcessFunctionParams): Promise<AppResponse> {
  // Publish an event
  await publishEvent(
    params,
    {
      productId: params.data.id,
      productName: params.data.name,
    },
    ProviderKey.COMMERCE,
    EventCode.PRODUCT_CREATED
  );

  return actionSuccessResponse("Event published successfully");
}

Available Event Codes

  • EventCode.PRODUCT_CREATED: Product creation events
  • Additional event codes can be added as needed

Available Provider Keys

  • ProviderKey.COMMERCE: Adobe Commerce provider
  • ProviderKey.BACKOFFICE: Backoffice provider

State Management

The template includes state management utilities using Adobe I/O lib-state:

State Management Example

import { getStateClient } from "../../utils/lib-state/state-client";

export async function main(params: ProcessFunctionParams): Promise<AppResponse> {
  // Use lib state for temporary storage
  const stateClient = await getStateClient();
  await stateClient.put("key", "value", {
    ttl: 1000 * 60 * 60 * 24, // 24 hours
  });

  // Retrieve data
  const value = await stateClient.get("key");

  return actionSuccessResponse("State operation completed");
}

File Storage

The template includes file storage utilities using Adobe I/O lib-files:

File Storage Example

import { getStorageClient } from "../../utils/lib-files/storage-client";

export async function main(params: ProcessFunctionParams): Promise<AppResponse> {
  // Use lib files for permanent storage
  const filesClient = await getStorageClient();

  // Write file
  await filesClient.write("path/to/file.txt", "content");

  // Read file
  const content = await filesClient.read("path/to/file.txt");

  return actionSuccessResponse("File operation completed");
}

Complete Example

Here's a complete example showing all features together:

import { initializeLogger, logError } from "../../logger";
import { actionErrorResponse, actionSuccessResponse } from "../../responses";
import { getStateClient } from "../../utils/lib-state/state-client";
import { getStorageClient } from "../../utils/lib-files/storage-client";
import { AppResponse, HttpStatus } from "../../types/request";
import { AdobeCommerceClient } from "../../utils/adobe-commerce/adobe-commerce-client";
import { EventCode, ProviderKey, publishEvent } from "../../utils/io-events/adobe-events-api";
import { Product } from "./types/product";
import { ProcessFunctionParams } from "./types/request";

export async function main(params: ProcessFunctionParams): Promise<AppResponse> {
  initializeLogger("process-function");

  try {
    validateProduct(params.data);

    const storeConfig = { storeCode: "us", storeUrl: "https://us.example.com" };
    const client = AdobeCommerceClient.create(params, storeConfig);

    // Make Adobe Commerce API calls
    const products = await client.get("/rest/V1/products");

    // Publish event
    await publishEvent(
      params,
      {
        productId: params.data.id,
        productName: params.data.name,
      },
      ProviderKey.COMMERCE,
      EventCode.PRODUCT_CREATED
    );

    // Use lib state for temporary storage
    const stateClient = await getStateClient();
    await stateClient.put("key", "value", {
      ttl: 1000 * 60 * 60 * 24, // 24 hours
    });

    // Use lib files for permanent storage
    const filesClient = await getStorageClient();
    await filesClient.write("path", "content");

    return actionSuccessResponse("Product review summarization completed");
  } catch (error: unknown) {
    const errorMessage = error instanceof Error ? error.message : "Unknown error";
    logError(`Server error: ${errorMessage}`);
    return actionErrorResponse(HttpStatus.INTERNAL_ERROR, `Request failed: ${errorMessage}`);
  }
}

function validateProduct(product: Product): void {
  if (!product.id) {
    throw new Error("Product ID is required");
  }
}

Development Workflow

Available Scripts

# Build TypeScript to JavaScript
npm run build

# Watch for changes and rebuild
npm run watch

# Run tests
npm test

# Lint code
npm run lint

# Fix linting issues
npm run lint:fix

Development Process

  1. Write TypeScript in actions-src/
  2. Build with npm run build (or use npm run watch for development)
  3. Test with npm test
  4. Deploy - Adobe App Builder uses the compiled JavaScript in actions/

Environment Variables

The template expects these environment variables for Adobe Commerce integration:

OAuth 1.0a Authentication

  • COMMERCE_BASE_URL: Adobe Commerce instance URL
  • COMMERCE_CONSUMER_KEY: OAuth consumer key
  • COMMERCE_CONSUMER_SECRET: OAuth consumer secret
  • COMMERCE_ACCESS_TOKEN: OAuth access token
  • COMMERCE_ACCESS_TOKEN_SECRET: OAuth access token secret

IMS Authentication

  • OAUTH_CLIENT_ID: Adobe IMS client ID
  • OAUTH_CLIENT_SECRET: Adobe IMS client secret
  • OAUTH_SCOPES: Required scopes
  • OAUTH_HOST: IMS host URL

Adobe IO Events

  • OAUTH_ORG_ID: Adobe organization ID
  • IO_MANAGEMENT_BASE_URL: IO Events management base URL
  • IO_CONSUMER_ID: IO Events consumer ID
  • IO_PROJECT_ID: IO Events project ID
  • IO_WORKSPACE_ID: IO Events workspace ID

Testing

The template includes Jest for testing with TypeScript support:

// test/adobe-commerce-client.test.ts
import { AdobeCommerceClient } from "../actions-src/utils/adobe-commerce/adobe-commerce-client";

describe("AdobeCommerceClient", () => {
  test("should create client with OAuth 1.0a", () => {
    // Test implementation
  });
});

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published