# Aerosync Web SDK

This Web SDK provides an interface to load Aerosync-UI in Javascript/typescript application. Securely link your bank account through your bank’s website. Log in with a fast, secure, and tokenized connection. Your information is never shared or sold.

## Installation

```sh
npm i aerosync-web-sdk
```

## Usage

##### 1. Create the necessary HTML elements to trigger and host the AeroSync widget.

##

```html
<!-- Button to launch the AeroSync widget -->
<!-- 'id' is optional but useful for CSS/JS targeting -->
<!-- Vue syntax, replace with onclick="openAerosyncWidget()" if using plain JS -->
<button
  id="openBank"
  class="button"
  role="button"
  @click="openAerosyncWidget()"
>
  Connect Bank
</button>

<!-- This div is where the AeroSync widget iframe will be embedded -->
<!-- Make sure the 'id' here matches the 'elementId' passed during initialization -->
<div id="widget"></div>
```

##### 2. Import and Configure the AeroSync Widget

##

```typescript
/**
 * Step-by-step integration of AeroSync AddBank widget
 */
import type {
  AerosyncWidget,
  WidgetSuccessPayload,
  WidgetEventType,
} from "aerosync-web-sdk";
import { initAeroSyncWidget } from "aerosync-web-sdk";

function openAerosyncWidget() {
  // Initialize the widget with configuration options
  let widgetControls = initAeroSyncWidget({
    elementId: "widget", //  ID of the target div in your HTML
    iframeTitle: "Connect", //  Used for accessibility
    environment: "production", //  Set to 'sandbox' for testing, 'production' for live
    token: "xxxx", //  Your secure AeroSync token
    aeroPassUserUuid: "xxxx", //  Your AeroPass User UUID
    theme: "light", //  Only 'light' or 'dark' are supported

    // Event listener for all widget events
    onEvent(event: WidgetEventType) {
      console.log("event", event);
    },

    // Fires when the widget is fully loaded
    onLoad() {
      console.log("onload");
    },

    // Called after the user successfully connects a bank and closes the widget
    onSuccess(event: WidgetSuccessPayload) {
      console.log("onSuccess", event);
      if ("accounts" in event) {
        // multi-account: event.accounts = [{ connectionId, accountType, accountNumberDisplay }]
      } else {
        // single account: event.connectionId
      }
      // Handle success (e.g., update UI, send data to backend, etc.)
    },

    // Fires when the widget is closed manually by the user
    onClose() {
      console.log("widget closed");
    },

    // Catch and handle widget errors
    onError(event: string) {
      console.log("onError", event);
    },
  });

  // Launch the widget
  widgetControls.launch();
}
```

## Widget methods

`initAeroSyncWidget(...)` returns a controller with the following methods:

| Method | Description |
| --- | --- |
| `launch()` | Opens the widget. |
| `exit()` | Closes the widget programmatically (removes the iframe / closes the popup) and fires `onClose`. |
| `toggleTheme(value)` | Switches the theme at runtime. `value` must be `'light'` or `'dark'`. |
| `destroy()` | Tears down the widget and removes its event listeners. **Call this when your component unmounts** (see Lifecycle & cleanup). |

```typescript
widgetControls.launch();
widgetControls.toggleTheme("dark");
widgetControls.exit();
widgetControls.destroy();
```

## Lifecycle & cleanup (React / Vue / SPA)

In single-page apps, always call `destroy()` when the host component unmounts.
Otherwise the widget's `message` event listener (and any mounted iframe) leaks
across navigations and re-mounts.

```typescript
// React
useEffect(() => {
  const widget = initAeroSyncWidget({ /* ...config */ });
  widget.launch();
  return () => widget.destroy(); // cleanup on unmount
}, []);
```

```typescript
// Vue
onUnmounted(() => {
  widgetControls?.destroy();
});
```

## Configuration options

In addition to the required fields shown above (`elementId`, `iframeTitle`,
`environment`, `token`, `aeroPassUserUuid`, and the `on*` callbacks), the
following optional fields are supported:

| Option | Type | Description |
| --- | --- | --- |
| `theme` | `'light' \| 'dark'` | Widget theme. Defaults to `'light'`. |
| `style` | `{ bgColor?, opacity?, width?, height? }` | Visual overrides for the widget container, including custom `width` / `height`. |
| `embeddedBankView` | `{ elementId, width?, height?, onEmbedded }` | Renders the bank-selection list embedded in your page instead of in the modal. |
| `deeplink` | `string` | Deep link into a specific step/flow of the widget. |
| `handleOAuthManually` | `boolean` | Lets your app handle the OAuth redirect instead of the SDK. |
| `handleMFA` | `boolean` | Enables manual handling of MFA flows. |
| `jobId` | `string` | Resume / relink an existing job. |
| `connectionId` | `string` | Resume / relink an existing connection. |
| `configurationId` | `string` | Server-side configuration profile to apply. |
| `manualLinkOnly` | `boolean` | Restricts the flow to manual (non-OAuth) linking only. |
| `targetDocument` | `ShadowRoot` | Mounts the widget inside a Shadow DOM root instead of the main document. |

## Event payloads

The `on*` callbacks receive typed payloads:

```typescript
// onSuccess - fired after the user successfully links account(s).
// The payload is a union: single-account, or multi-account when the client
// has multi-account linking enabled. Narrow with `"accounts" in event`.
type WidgetSuccessPayload =
  | WidgetEventSuccessType
  | WidgetEventMultiAccountSuccessType;

// single account (AeroPass returning user + AeroPass link-new-bank)
interface WidgetEventSuccessType {
  connectionId: string;
  clientName: string;
  aeroPassUserUuid: string;
}

// multi-account (enable_multiple_account_linking)
interface WidgetEventMultiAccountSuccessType {
  accounts: {
    connectionId: string;
    accountType: string;
    accountNumberDisplay: string;
  }[];
  clientName: string;
  aeroPassUserUuid: string;
}

// onEvent - fired for general widget lifecycle events
interface WidgetEventType {
  type: string;
  payload: {
    pageTitle: string;
    onLoadApi: string;
  };
}

// onError receives an error message string
// onLoad and onClose receive no arguments
```

## Readme.io document

For more information check the complete guide here: https://sync.dev.aero.inc/docs/npm-aeronetwork
