Ir al contenido

Vimine (navegador)

Ver como Markdown
import { Vimine } from '@vimine/sdk';
const vimine = new Vimine(options);

Vimine gestiona Iniciar sesión con Vimine (OAuth 2.1 + PKCE), la sesión del socio y las llamadas a la API de socios. Una instancia por cliente; créala una vez y reutilízala.

Opción Tipo Por defecto
clientId string — tu vmc_… (obligatorio)
redirectUri string — la página que llama a handleRedirect(), registrada para el cliente (obligatorio)
scopes Scope[] ['profile:read', 'membership:read'] permisos que solicita signIn()
storage 'session' | 'local' | 'memory' | TokenStorage 'session' dónde viven la sesión y el inicio de sesión en curso
storageKey string vimine:<clientId>: prefijo de las claves en el almacenamiento
locale Locale 'it' idioma de las páginas de inicio de sesión y de consentimiento
apiUrl string https://api.vimine.network origen de la API
appUrl string https://app.vimine.network origen de las páginas de inicio de sesión
fetch typeof fetch globalThis.fetch para tests y polyfills
navigate (url) => void top.location.assign cómo salir de la página

El constructor lanza un VimineError (invalid_options) sin clientId o redirectUri.

Envía la ventana principal a la página de inicio de sesión y de consentimiento. Llámalo desde un gesto del usuario (un clic). Desde dentro de un iframe de otro origen la navegación se rechaza (framed): la página de inicio de sesión nunca se muestra en un marco.

Opción
scopes permisos de este inicio de sesión
prompt 'login' (credenciales siempre) o 'consent' (consentimiento siempre)
returnTo tu propio estado, guardado localmente y devuelto por handleRedirect() — no se envía

Construye la URL de autorización y recuerda el inicio de sesión en curso (verificador PKCE y state) sin navegar. Útil cuando dibujas tú el enlace.

true cuando la URL (por defecto: la página actual) lleva los parámetros de una vuelta (code+state o error).

En la página de callback: comprueba el state, intercambia el código por los tokens y guarda la sesión. Devuelve { session, returnTo }, o null cuando la URL no lleva parámetros de inicio de sesión. Con cleanUrl (por defecto true) quita code, state y error de la barra de direcciones.

Errores (VimineError.code): access_denied y los demás errores OAuth cuando el socio no ha autorizado; no_flow cuando no se ha iniciado ningún inicio de sesión desde este navegador (almacenamiento vacío o caducado); state_mismatch cuando la vuelta no corresponde; invalid_grant cuando el código ha caducado o ya se ha usado.

La sesión guardada, o null.

interface Session {
accessToken: string;
refreshToken: string | null;
expiresAt: number; // ms, absoluto
scope: Scope[];
sub: string | null; // el identificador del socio para tu asociación (vms_…)
mode?: 'live' | 'test'; // 'test' para las sesiones de un cliente de prueba
}

Un token de acceso válido, renovado cuando caduca en menos de 30 segundos. Lanza not_signed_in si no hay sesión.

Rota la sesión con el refresh token (una sola petición aunque se llame de forma concurrente). Cuando el refresh token ya no se puede usar, la sesión se borra y el error se vuelve a lanzar.

signOut({ everywhere?, postLogoutRedirectUri?, state? })

Sección titulada «signOut({ everywhere?, postLogoutRedirectUri?, state? })»

Revoca el refresh token (RFC 7009, en la medida de lo posible) y olvida la sesión. Con everywhere: true, después envía el navegador al /oauth/logout de la app de Vimine, que cierra la sesión del socio y vuelve a postLogoutRedirectUri (por defecto redirectUri; debe estar en un origen registrado).

listener(session | null) en cada inicio de sesión, renovación y cierre de sesión; con storage: 'local', también para los que ocurren en otras pestañas. Devuelve la función para cancelar la suscripción.

Una llamada autenticada: Authorization: Bearer, JSON de entrada y de salida, errores como VimineError, un reintento después de una renovación cuando la respuesta es 401. init.idempotencyKey se convierte en la cabecera Idempotency-Key.

const events = await vimine.request('/v1/me/membership/events?limit=5');
Scope
me.get() profile:read el perfil (Me), con codicefiscale_check: cómo está identificada la persona (null = todavía no)
me.update(patch) profile:write teléfono, sexo, y la identificación: fecha, lugar y país de nacimiento (birth_country), código fiscal — opcional, se puede añadir más tarde. Un código que no coincide responde 422 con una entrada codicefiscale_mismatch; cuando es confirmable, la persona lo confirma con codicefiscale_confirmed: true (guía)
Scope
membership.get() membership:read el carné: status, verdict, expires_at, statuto, card
membership.request(body, { idempotencyKey? }) membership:request solicitud de inscripción; se genera una clave de idempotencia si falta. 422 identification_required cuando el perfil no está identificado: err.errors indica lo que falta, que se completa con me.update()
membership.events({ limit?, cursor? }) membership:read historial de estados, paginado
membership.statuto() membership:read el estatuto en vigor y la aceptación del socio
membership.acceptStatuto({ version, sha256? }) statuto:accept registra la aceptación
membership.card() membership:read el token del carné (QR) y su ventana; 409 not_active salvo que la inscripción esté activa
membership.renew({ version, sha256? }) POST /v1/me/membership/renew renovación por cuenta propia: inmediata si es gratuita y sin aprobación; si no, una solicitud a la secretaría
membership.setNetworkOptIn(bool) PATCH /v1/me/membership/network-opt-in consentimiento al Network (network:manage)
membership.googleWalletUrl() GET /v1/me/membership/wallet/google un enlace «Guardar en Google Wallet»; 409 not_active salvo que la inscripción esté activa
membership.cardSvg() GET /v1/me/membership/card.svg el carné en SVG (con el QR); 409 not_active salvo que la inscripción esté activa
membership.emailCard() POST /v1/me/membership/card/email envía al socio su carné por correo

Los eventos publicados de la asociación, incluidos los que son solo para socios (events:read). Los públicos no necesitan iniciar sesión: vimine.public.events.

events.list({ filter?, from?, to?, limit? }) filter: upcoming (por defecto), past, cancelled, all
events.get(slug) contenido, imágenes, tipos de inscripción con las plazas que quedan
events.eligibility(slug) ¿puede inscribirse el socio? por tipo, con los motivos (membership_required, sold_out, …)

Las inscripciones del socio (registrations:read / registrations:write). Consulta la guía Eventos e inscripciones.

registrations.create(slug, { registration_type, note?, quantity? }, opts?) tipo gratuito → confirmed con el token del QR; con contribución → reserved con payment_instructions; 422 not_eligible con los motivos; Idempotency-Key generada
registrations.list({ filter? }) · registrations.get(id) las inscripciones del socio (filter: 'upcoming')
registrations.cancel(id) anula dentro de la ventana del evento (después, 409 window_closed)
registrations.tokenPayload(id) el contenido del QR de una inscripción confirmada, o null
connections.list() las apps que el socio ha autorizado en esta asociación
connections.revoke(clientId) retira el consentimiento a una app (sus sesiones terminan)

Los endpoints públicos, sin credenciales: consulta publicApi.

storage Dónde Cuándo
'session' (por defecto) sessionStorage: por pestaña, desaparece al cerrarla la opción por defecto más segura para un cliente público
'local' localStorage: compartido entre pestañas, sobrevive a los reinicios; el cierre de sesión se propaga a las demás pestañas apps en las que el socio espera seguir con la sesión iniciada
'memory' solo en memoria SSR, tests, quioscos
TokenStorage un objeto tuyo { get, set, remove } Node, almacenamientos cifrados, apps nativas

Cuando el almacenamiento del navegador no está disponible (modo privado, about:blank), el SDK recurre a la memoria. Se exporta MemoryStorage.

  • createPkce() → { verifier, challenge, method: 'S256' }, createVerifier(), createChallenge(verifier), createState(), base64url(bytes) — PKCE y state sobre WebCrypto, si construyes el flujo a mano.
  • DEFAULT_API_URL, DEFAULT_APP_URL.
  • publicApi(options?) — consulta API pública.
  • VimineError — consulta Errores.