@andco/sdk/cli

El constructor de terminal y el presentador con receptor loopback.

ts
import { AndcoCliPresenter, createAndcoInstanceForCLI } from "@andco/sdk/cli";

createAndcoInstanceForCLI

ts
createAndcoInstanceForCLI(options: AndcoCliOptions): AndcoSessionClient

Un cliente público con sesión, como el de navegador, pero con un presentador de terminal y sin suponer que existe window. AndcoCliOptions son las opciones del cliente con sesión, con presenter opcional.

ts
const andco = createAndcoInstanceForCLI({
  clientId: "tu-client-id",
  redirectTo: "http://127.0.0.1:0/callback",
  storage: keychain,
  presenter: new AndcoCliPresenter({ open: (url) => openInBrowser(url.href) }),
});

AndcoCliPresenter

ts
new AndcoCliPresenter(options?: AndcoCliPresenterOptions)
Opción Por omisión Qué hace
open imprimir abre la URL de autorización
print recibe el mensaje cuando no se puede abrir un navegador
timeoutMs 10 minutos cuánto se espera a que la persona termine

Levanta un receptor loopback de un solo uso: se ata al puerto, rechaza cualquier ruta que no sea la registrada, comprueba el state, responde una vez y cierra.

Todo integrador de línea de comandos necesita exactamente esto, y hasta ahora cada uno lo escribía. La versión de la propia CLI de Andco tenía noventa líneas. Equivocarse en cualquier parte —aceptar el callback en otra ruta, saltarse la comprobación del state, dejar el puerto abierto— es un fallo de seguridad en la herramienta de alguien.

El callback tiene que ser http sobre un host de loopback; cualquier otra cosa se rechaza con invalid_configuration.

Puerto libre

ts
redirectTo: "http://127.0.0.1:0/callback";

El puerto 0 pide uno libre al sistema. El presentador reemplaza el redirect_uri de la autorización por el puerto que realmente obtuvo, porque el servidor de autorización tiene que redirigir a esa URI exacta.

Flujo de dispositivo

Cuando no hay navegador que abrir:

ts
const { data: device } = await andco.oauth.createDeviceAuthorizationRequest({ scopes: ["openid", "email"] });
console.log(`Abre ${device.verificationUriComplete} y escribe ${device.userCode}`);

const { data: session } = await andco.oauth.awaitDeviceAuthorization(device);
await andco.session.set(session);

AndcoDeviceAuthorization trae deviceCode, userCode, verificationUri, verificationUriComplete, expiresIn, interval y la respuesta cruda.

awaitDeviceAuthorization hace el sondeo completo: respeta el intervalo, obedece los avisos de ir más lento y termina cuando la autorización se aprueba, se rechaza o vence. Acepta signal para cancelar.

Persistir la sesión

El almacenamiento por omisión vive en memoria y desaparece con el proceso. Para que la persona no se autentique en cada comando, entrega el tuyo:

ts
const andco = createAndcoInstanceForCLI({ clientId, redirectTo, storage: keychain, lock: crossProcessLock });

lock importa cuando varios comandos pueden correr a la vez: los refresh tokens rotan, y dos renovaciones simultáneas invalidan una a la otra.