# @andco/sdk/browser

> El constructor de navegador, el botón hospedado, la ventana emergente y el relevo del callback.


```ts
import { createAndcoInstanceForBrowser } from "@andco/sdk/browser";
```

## createAndcoInstanceForBrowser

```ts
createAndcoInstanceForBrowser(options: AndcoBrowserOptions): AndcoSessionClient
```

Construir no hace entrada ni salida. El único efecto que sí ocurre es el relevo de la ventana emergente, y solo cuando se cumplen cinco condiciones a la vez: el documento tiene un `opener`, su `window.name` lleva un Presentation ID válido, la URL trae parámetros de callback, el estado se puede leer y su origen está permitido. Una página normal falla las dos primeras y la llamada no hace nada.

El intercambio del código **no** ocurre aquí: es una escritura de credencial, el código es de un solo uso, y una construcción que el framework descarta no debe gastarlo. Ocurre en la primera lectura del almacén.

`AndcoBrowserOptions` es lo mismo que las opciones del cliente con sesión, más:

| Opción | Por omisión | Qué hace |
| --- | --- | --- |
| `detectSessionInUrl` | `true` | intercambia el código que la redirección dejó en la URL |
| `relayPopupCallback` | `true` | entrega el callback al `opener` cuando este documento es una ventana emergente de Andco |
| `replaceUrl` | History API | cómo se limpia la URL después de consumirla |
| `transactionStorage` | `sessionStorage` | dónde vive la transacción entre la redirección y la vuelta |
| `presenter` | `browserPresenter()` | cómo se presenta la autorización |
| `storage` | `sessionStorage` | dónde vive la sesión |
| `initialSession` | — | una sesión ya resuelta, para que el primer cuadro sea real |

`clientSecret` está rechazado por tipos: una credencial confidencial no puede llegar a un navegador.

## browserPresenter

```ts
browserPresenter(): AndcoPresenter
```

Detecta el Host nativo de Andco y enruta por el puente en vez de abrir una ventana, de modo que una Miniapp corre el mismo build dentro del Host y en una pestaña. Por eso no existe un presentador de móvil ni un constructor aparte.

## AndcoButtonController

Coordina el iframe hospedado sin decidir cómo lo renderiza tu framework.

```ts
new AndcoButtonController(options: AndcoButtonControllerOptions)

subscribe(listener: (snapshot: AndcoButtonSnapshot) => void): () => void
connect(iframe: HTMLIFrameElement): () => void
disconnect(): void
restart(): void
destroy(): void
get snapshot: AndcoButtonSnapshot
```

Opciones: `client`, `authorization`, `flow` (`"authorization"` o `"intent"`), `presentation`, `release`, `themeMode`, `locale`, `disabled`, `busy`, y los callbacks `onReady`, `onActivate`, `onComplete`, `onDismiss`, `onError`.

`AndcoButtonSnapshot` lleva `status`, `iframeURL`, `ready` y `error`. Los estados son `idle`, `connecting`, `ready`, `authorizing`, `complete`, `dismissed` y `error`.

El iframe es de Andco y es de otro origen: su DOM y su código no son del Proyecto, y el manejador de la ventana emergente nunca entra en JavaScript del Proyecto. No es una frontera de autorización y no protege los tokens del Proyecto.

## Ventana emergente

```ts
openAndcoPopupWindow(options: {
  presentationId: string;
  expectedOrigin: string;
  url?: URL;
  signal?: AbortSignal;
}): AndcoPopupWindow
```

`AndcoPopupWindow` tiene `blocked`, `navigate(url)`, `result` y `close()`.

Abrir primero y navegar después es lo que permite un flujo cuyo destino requiere una ida al servidor: el navegador solo concede `window.open` durante un gesto de la persona, así que la ventana ya está esperando cuando tu backend responde.

`blocked` existe para que puedas abandonar antes de hacer trabajo en el servidor: una ventana bloqueada que igual disparó una autorización deja una transacción que nadie puede completar.

```ts
openAndcoPopup(options): Promise<Result<URL | null>>
```

Versión directa, para cuando ya conoces el destino.

## Relevo del callback

```ts
relayAndcoPopupCallback(allowedOrigins: ReadonlySet<string>, options?: { callbackUrl?: string | URL }): AndcoRelayOutcome
andcoPopupPresentationId(): string | null
isAndcoNativeHost(): boolean
```

El relevo entrega el callback a quien abrió la ventana y se cierra. Es un mensajero, no un consumidor: el verificador PKCE lo generó el `opener` y nunca salió de ahí.

A quién le habla lo decide quién abrió la ventana. Un `opener` en el mismo origen es la ventana propia del SDK y recibe la URL completa del callback; un `opener` de otro origen es la superficie hospedada de Andco y recibe un resultado del Protocol Contract.

`callbackUrl` existe para un flujo conducido por el servidor del Proyecto, donde no hay un código de autorización que reconocer y quien llama afirma qué entregar.

`AndcoRelayOutcome` es `not_callback`, `not_popup`, `relayed` o `rejected`.
