# eturnityConsentBridge

Lightweight browser bridge for synchronizing consent-related cookie payloads between a host page and an embedded Eturnity iframe via `postMessage`.

## Overview

`eturnityConsentBridge` is a public browser/CDN script that exposes a global function:

- `window.eturnityConsentBridge(...)`
- `eturnityConsentBridge(...)`

It is designed for third-party embedding on customer websites and supports multiple bridge instances (multiple iframes) on the same page.

## Features

- Global API for plain HTML and JavaScript-based script injection flows
- Safe message routing per iframe instance using `event.source` and origin checks
- Idempotent initialization for repeated calls with the same iframe ID
- Non-throwing input validation (returns `null` on invalid init input)
- Cookie fallback persistence and replay on iframe sync-ready handshake
- Optional debug logging with `logs: true`
- Lifecycle helpers: per-instance and global cleanup

## Installation

### 1) CDN script tag

```html
<script src="https://ABSOLUTE_CDN_LINK/eturnity-consent-bridge.min.js"></script>
```

### 2) Dynamic script injection

```js
const script = document.createElement('script')
script.src = 'https://ABSOLUTE_CDN_LINK/eturnity-consent-bridge.min.js'
script.async = true
script.addEventListener('load', () => {
  window.eturnityConsentBridge('my-iframe-id', { type: 'solar_calculator' })
}, { once: true })
document.body.appendChild(script)
```

## Usage

After the script is loaded, initialize per iframe:

```js
eturnityConsentBridge('my-iframe-id', {
  type: 'solar_calculator',
  logs: false,
})
```

Initialization returns:

- instance object on success
- `null` when validation fails

The iframe can be missing at init time; the bridge will keep trying to resolve it during message handling.

## Message Contract

All message names are namespaced by selected `type`:

- `eturnity_<type>_cookie_sync_ready` (iframe -> host)
- `eturnity_<type>_cookie_fallback` (iframe -> host)
- `eturnity_<type>_cookie_delete` (iframe -> host)
- `eturnity_<type>_cookie_sync` (host -> iframe)

### Payloads

- `cookie_fallback` payload:
  - `{ cookieName: string, cookieValue: string }`
- `cookie_delete` payload:
  - `{ cookieName: string }`
- `cookie_sync` payload for set/update replay:
  - `{ cookieName: string, cookieValue: string }`
- `cookie_sync` payload for delete replay:
  - `{ cookieName: string, isDeleted: true }`

`isDeleted: true` is the delete marker for iframe listeners.

### Replay lifecycle (important)

Stored cookie replay can be triggered in two safe ways:

- **on init**: right after bridge initialization (`eturnityConsentBridge(...)`)
- **on handshake**: when iframe sends `eturnity_<type>_cookie_sync_ready`

The init replay exists to avoid reload race conditions where the iframe handshake might be sent before the host bridge is fully attached.

Delete events are also synchronized: when iframe sends `eturnity_<type>_cookie_delete`, host removes that entry from its cache and then emits `eturnity_<type>_cookie_sync` with `{ cookieName, isDeleted: true }`.

## API

### `eturnityConsentBridge(iframeId, options)`

Creates or updates a bridge instance for a target iframe.

- **`iframeId`**: `string` (required)
  - Accepts values with or without leading `#`
- **`options`**: `object` (required)
  - See [Options](#options)

**Returns**

- `BridgeInstance` on success
- `null` on invalid input

### `eturnityConsentBridge.destroy(iframeId)`

Destroys one bridge instance.

- Returns `true` if an instance was removed, otherwise `false`.

### `eturnityConsentBridge.destroyAll()`

Destroys all bridge instances and removes the shared `message` listener when no instances remain.

### `BridgeInstance.destroy()`

Returned instance includes `destroy()` to remove itself.

## Options

```ts
type BridgeOptions = {
  type: 'solar_calculator' | 'heating_calculator' | 'e_mobility_configurator'
  logs?: boolean
}
```

- **`type`** (required): selects internal message/cookie namespace
- **`logs`** (optional, default `false`): enables verbose console logging for this instance

Unknown option keys are ignored.

## Examples

### Basic

```html
<iframe id="eturnity-solar" src="https://example-iframe-host/path"></iframe>
<script src="https://ABSOLUTE_CDN_LINK/eturnity-consent-bridge.min.js"></script>
<script>
  eturnityConsentBridge('eturnity-solar', { type: 'solar_calculator' })
</script>
```

### Multiple iframes on one page

```js
eturnityConsentBridge('solar-iframe', { type: 'solar_calculator' })
eturnityConsentBridge('heating-iframe', { type: 'heating_calculator', logs: true })
```

### Re-initialize same iframe (idempotent update)

```js
eturnityConsentBridge('solar-iframe', { type: 'solar_calculator', logs: false })
eturnityConsentBridge('solar-iframe', { type: 'solar_calculator', logs: true }) // updates existing instance
```

### Cleanup

```js
const instance = eturnityConsentBridge('solar-iframe', { type: 'solar_calculator' })
instance && instance.destroy()

eturnityConsentBridge.destroy('heating-iframe')
eturnityConsentBridge.destroyAll()
```

## Troubleshooting

### `Missing iframe id` or `Invalid options.type`

- Ensure `iframeId` is a non-empty string.
- Ensure `options.type` is one of:
  - `solar_calculator`
  - `heating_calculator`
  - `e_mobility_configurator`

### `Iframe ... was not found during initialization`

- Verify iframe ID matches exactly.
- If iframe is rendered later, you can initialize early; bridge resolves context again during runtime.

### `Could not resolve iframe origin`

- Ensure iframe has a valid `src` URL.

### `Ignoring ... due to origin mismatch`

- Host and iframe messaging origins must match the iframe `src` origin resolved by the bridge.

### Why replay may happen before `cookie_sync_ready`

- This is expected behavior: replay on init is intentional and does not depend on handshake timing.
- In some page-load orders, the iframe can emit `cookie_sync_ready` before the host bridge listener is attached; in that case you may not see a handshake log.
- This does not break integration: the iframe consumes `eturnity_<type>_cookie_sync` messages directly, and `cookie_sync_ready` is only a replay signal from iframe to host.

### Cookie warning on non-HTTPS host

- The bridge writes cookies with `Secure`; on non-HTTPS pages browsers may reject persistence.
- Use HTTPS in production embedding environments.
