npm package: @hejsoftware/cti-plugin-lib
Description: Library to simplify the development of plugins for the Hej Software Computer Telephony Integration (see [gethej.com](https://gethej.com)).
Author: Hej Software UG
Latest version: 1.2.1

# Hej Software CTI Plugin Lib

Library to simplify the development of plugins for the Hej Software Computer Telephony Integration
(see [gethej.com](https://gethej.com)).

You can find quick start projects here:

- [JavaScript](https://github.com/hejsoftware/cti-plugin-js-starter)
- [TypeScript](https://github.com/hejsoftware/cti-plugin-ts-starter)

As well as a small example plugin [here](https://github.com/hejsoftware/cti-plugin-example).

## Architectural overview

A CTI plugin consist of three parts: A __manifest__, the __background service__ and, optionally, a __view__.

```
[ CTI extension ]
       ||
( call updates )
       ||
       \/
   [ Service ] ==( updates )==> [ Plugin State ] ==( rendered by )=> [ View ]
       /\                                                               ||
       ||                                                               ||
       \\=====================( dispatches events )=====================//
```


### The manifest

The manifest should be a JSON file that conforms the the following interface:

```typescript
interface IPluginDefinition {
    /**
     * Manifest definition version, currently always 1
     */
    readonly manifestVer: 1;

    /**
     * Human readable name
     */
    readonly name: string;

    /**
     * Plugin version
     */
    readonly version: string;

    /**
     * URL to background service
     */
    readonly serviceUrl: string;

    /**
     * URL to the view, optional.
     */
    readonly viewUrl?: string;
}
```

### Background service

The background service is loaded into an IFrame from the URL specified by the `serviceUrl` property in the manifest.

The entry point for the service should look something like this:
```typescript
import { startService, ICtiPluginService, ITelephonyApi, ICallApi, Call } from "@hejsoftware/cti-plugin-lib";

class MyPluginService implements ICtiPluginService {
    public start(telephonyApi: ITelephonyApi) {
        // Your implementation here
        
        telephonyApi.onCall((initial: Call, callApi: ICallApi) => {
            // Call handler impl.
        });
    }
}

startService(new MyPluginService());
```

The `start()` method is called the moment communication has been established with the CTI extension.
From this moment on the service is kept running permanently.

### View (Optional)

In charge of rendering the view portion presented to the end user. It will receive __plugin state__ update events when
it is updated by the __call handler__ in the background service.

It should not contain any logic as there is no guarantee that it will stay loaded permanently or be loaded at all,
for ex.: User switches between calls, causing the plugin view for the one he switched away to be unloaded.
Also, multiple views for the same call can be rendered (multiple CTI sidebars open), causing the logic to be executed 
multiple times.

Because of the above, the view can not update the call state directly, instead you should dispatch __view events__ using
the `dispatch` function provided to the `start()` method.

```typescript
import { startView, ICtiPluginView, DispatchEventFn } from "@hejsoftware/cti-plugin-lib";

class MyPluginView implements ICtiPluginView<S = any> {
    protected dispatch: DispatchEventFn;
    
    protected myBtn = document.getElementById("myButton") as HTMLButtonElement;
    
   /**
    * Called once after establishing connection with the CTI extension 
    */
    public start(dispatch: DispatchEventFn) {
        this.dispatch = dispatch;
        
        
        // Can trigger custom events the background service should react to
        this.myBtn.addEventListener("click", () => this.dispatch({
            event: "MY_BUTTON_CLICK",
        }));
    }
    
   /**
    * Called every time the state is updated by the background service
    */
    public render(state) {
        // Should render/update the UI based on the new state
    }
}
```