npm package: @kustomer/apps-server-sdk
Description: Kustomer Server Side App SDK
Latest version: 0.0.60

# @kustomer/apps-server-sdk

A JavaScript/TypeScript SDK to build apps within Kustomer.

[Getting Started](#gettings-started)  
[Initializing An App](#initializing-an-app)  
[Development](#development)
  - [Klasses](#klasses)
  - [KViews](#kviews)
  - [Settings](#settings-pages)
  - [Commands](#commands)
  - [Hooks](#hooks)
  - [Events](#kustomer-events)
  - [Authorization](#authorization)
  - [Lifecycle Events](#lifecycle-events)
  - [API](#api)
  - [Custom Endpoints](#custom-endpoints)

## Getting Started

The following command will scaffold a basic app for you to build upon so you can quickly get started developing:

```bash
npm i -g @kustomer/apps-server-sdk && kapp new <your_desired_app_name>
```

## Initializing an App

Create an app by importing the `KApp` class and calling its constructor with our desired app configuration:

```typescript
import { KApp, ROLES } from '@kustomer/apps-server-sdk';

const app = new KApp({
  app: 'example_app',
  version: '1.0.0',
  title: 'Example App',
  visibility: 'public',
  url: 'https://my-example-app.example.com',
  clientId: 'your_client_id',
  clientSecret: 'your_client_secret',
  roles: ROLES.common,
  iconUrl: 'https://example-icon.com/assets/icon.png',
  env: 'qa',
  appDetails: {
    appDeveloper: {
      name: 'Kustomer',
      website: 'https://kustomer.com',
      supportEmail: 'support@kustomer.com'
    },
    externalPlatform: {
      name: 'Some External Platform',
      website: 'https://external-platform.example.com'
    }
  },
  description: 'Really great app description'
});

/* Your app functionality here */

(async () => {
  try {
    await app.start({ port: +(process.env.PORT || 80) });
  } catch (err) {
    app.log.error(JSON.stringify(err, undefined, 2));
  }
})();
```

## Development

Apps typically provide one or more components that add functionality to the Kustomer platform. Components are the building blocks that form the core of an app and allow you to do things such as create views in the agent timeline, custom objects that represent data in your app, settings that allow users to configure their app, webhooks for receiving data from external sources, and more.

### Klasses  

[Klasses](https://developer.kustomer.com/kustomer-apps-platform/docs/klasses) define schemas for data objects including custom objects (or KObjects) in the Kustomer platform.

A Kustomer app can create and configure custom Klasses to represent external domain objects such as e-commerce orders, survey results, or external customer interactions.

```typescript
// Adds a Klass to the app. The Klass will be created when an org installs the app.
app.useKlass('your-klass-name', {
  icon: 'example-icon',
  color: '#64943E',
  metadata: {
    properties: {
      examplePropNum: {
        displayName: 'Example Number Property'
      }
    }
  }
});
```

### KViews

[Klass Views](https://developer.kustomer.com/kustomer-apps-platform/docs/klass-views) (or KViews) display data for standard objects and for custom objects (or KObjects) on the agent timeline in Kustomer. The Kustomer platform renders Klass Views based on a JSX template.  

Apps can configure KViews for a Kustomer organization to customize timeline layouts, insight panels, insight cards, and insight details.

```typescript
// Adds a JSX view to the app using Kustomer's standard Klass views (KViews)
// The view must be passed in as a string
app.useView(
  'your-kview-name',
  fs.readFileSync(path.resolve(__dirname, 'your-kview.tsx'), { encoding: 'utf-8' }),
  {
    resource: 'kobject',
    context: 'expanded-timeline',
    displayName: 'Example Display Name',
    icon: 'example-icon',
    state: 'open'
  }
);
```

KViews can also be created with a fully custom view that is rendered via an iframe within Kustomer:

```typescript
// Adds a fully custom view to the app rendered via an iframe in Kustomer
app.useView('your-kview-name', '/path/to/view/directory', {
  resource: 'conversation',
  context: 'smartbar-card',
  displayName: 'Example Display Name',
  icon: 'example-icon',
  state: 'open'
});
```

### Settings Pages

You can create [custom settings pages](https://developer.kustomer.com/kustomer-apps-platform/docs/app-settings#app-settings-and-custom-settings-pages) to be rendered within an iframe in Kustomer. These custom pages Simply provide the path to the directory containing your index.html file and it will be served up to the front-end and rendered in place of Kustomer's default generated settings pages. 

```typescript
// Adds a custom settings view that will be rendered via iframe in place of Kustomer's default generated settings page.
app.useSettings('Settings Page Title', 'Example settings page description', '/path/to/settings/view');
```

### Commands

[Commands](https://developer.kustomer.com/kustomer-apps-platform/docs/commands) are reusable requests that can be executed through the Kustomer API. Commands provide a simple wrapper that allows custom components in Kustomer to interact with external services.

Apps can configure commands for use by Klass Views (KViews), widgets, or workflows also configured by the app. Apps can also configure commands to be available to custom code (for example, configuring a button within a KView to call a command).

Using the `action: true` option, you can choose to create a [workflow action](https://developer.kustomer.com/kustomer-apps-platform/docs/workflow-actions) from a command.

```typescript
// Adds a handler for a command that will be created when the app is installed.
app.onCommand('command-name', (orgId: string, userId: string, data: any) => { /* do some stuff */ });

// Adds a handler for a command and creates a workflow action from the command
app.onCommand('command-name', { action: true }, (orgId: string, userId: string, data: any) => { /* do some stuff */ });
```

### Hooks

Hooks allow you to define inbound webhooks that provide a way for external data to be sent to your app. Webhooks created by your app will be reachable at `<your-app-base-url>/orgs/:org/hooks/:hook`

```typescript
// Creates a webhook at https://your-app-name.example.com/orgs/:org/hooks/hook-name
app.onHook('hook-name', (org: string, query: any, headers: any, body: any) => { /* do some stuff */ });
```

### Kustomer Events

You can easily subscribe to events that occur within the Kustomer platform. The following events are currently available to subscribe to:

```
Customer create
Customer update
Team create
Team update
User create
User update
Message create
Message update
Conversation create
Conversation update
```

```typescript
// Subscribes to a customer create event in Kustomer
app.on('customer', 'create', (customer: Customer) => { /* do some stuff */ });
```

### Authorization

The SDK provides a way to easily handle authorization requests:

```typescript
// Handle authorization requests
app.onAuth(fn: express.RequestHandler);

// Handle authorization redirect requests
app.onAuthComplete(fn: express.RequestHandler);
```

### Lifecycle Events

The SDK enables you to react to certain app-related events:

```typescript
app.onInstall = (userId: string, orgId: string) { /* React to app installation */ }

app.onDisable = (userId: string, orgId: string) { /* React to an app being disabled */ }

app.onEnable = (userId: string, orgId: string) { /* React to an app being enabled */ }
```

### API

The SDK comes with an out-of-the-box ability to interface with the Kustomer API.

Requests can be made to an org using its id, name, or valid token.

Here is an example of us performing a customer upsert.

```typescript
let customer = await app.org('org_name_or_id_or_token').customers.getById('my_id');

if (!customer) {
  customer = await app.org('org_name_or_id_or_token').customers.create({ ... });
} else {
  customer = await app.org('org_name_or_id_or_token').customers.update(customer.id, { ... });
}
```

### Custom Endpoints

For app server customization that isn't officially supported by our apps platform, you can utilize the exposed express `app`.

**Be careful not to unintentionally override and endpoints used by the SDK itself or the app may not work as expected!**

```typescript
kapp.app.get('/hello-world', (_req, res, _next) => {
  res.send('hello world!');
});
```