Salta ai contenuti

Vimine (browser)

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

Vimine gestisce Accedi con Vimine (OAuth 2.1 + PKCE), la sessione del socio e le chiamate all’API del socio. Un’istanza per client; creala una volta e riusala.

Opzione Tipo Default
clientId string — il tuo vmc_… (obbligatorio)
redirectUri string — la pagina che chiama handleRedirect(), registrata per il client (obbligatorio)
scopes Scope[] ['profile:read', 'membership:read'] permessi chiesti da signIn()
storage 'session' | 'local' | 'memory' | TokenStorage 'session' dove vivono sessione e accesso in corso
storageKey string vimine:<clientId>: prefisso delle chiavi nello storage
locale Locale 'it' lingua delle pagine di accesso e consenso
apiUrl string https://api.vimine.network origine dell’API
appUrl string https://app.vimine.network origine delle pagine di accesso
fetch typeof fetch globalThis.fetch per test e polyfill
navigate (url) => void top.location.assign come lasciare la pagina

Il costruttore lancia VimineError (invalid_options) senza clientId o redirectUri.

Porta la finestra principale alla pagina di accesso e consenso. Chiamala da un gesto dell’utente (un click). Da dentro un iframe di un’altra origine la navigazione è rifiutata (framed): la pagina di accesso non si mostra mai in un frame.

Opzione
scopes permessi di questo accesso
prompt 'login' (credenziali sempre) o 'consent' (consenso sempre)
returnTo uno stato tuo, conservato in locale e restituito da handleRedirect() — non viene inviato

Costruisce l’URL di autorizzazione e memorizza l’accesso in corso (verifier PKCE e state), senza navigare. Utile se vuoi rendere tu il link.

true se l’URL (default: la pagina corrente) porta i parametri di un ritorno (code+state oppure error).

Nella pagina di callback: verifica lo state, scambia il codice con i token e salva la sessione. Restituisce { session, returnTo }, oppure null se l’URL non ha i parametri di un accesso. Con cleanUrl (default true) toglie code, state ed error dalla barra degli indirizzi.

Errori (VimineError.code): access_denied e gli altri errori OAuth se il socio non ha autorizzato; no_flow se nessun accesso era stato avviato da questo browser (storage vuoto o scaduto); state_mismatch se il ritorno non corrisponde; invalid_grant se il codice è scaduto o già usato.

La sessione salvata, o null.

interface Session {
accessToken: string;
refreshToken: string | null;
expiresAt: number; // ms, assoluto
scope: Scope[];
sub: string | null; // identificativo del socio per la tua associazione (vms_…)
mode?: 'live' | 'test'; // 'test' per le sessioni di un client di test
aps?: AssociationRef | null; // l'associazione: slug, name, picture_url
}

Un access token valido, rinnovato se scade entro 30 secondi. Lancia not_signed_in senza sessione.

Ruota la sessione con il refresh token (una sola richiesta anche se chiamata più volte in parallelo). Se il refresh token non è più utilizzabile la sessione viene cancellata e l’errore rilanciato.

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

Sezione intitolata “signOut({ everywhere?, postLogoutRedirectUri?, state? })”

Revoca il refresh token (RFC 7009, best effort) e dimentica la sessione. Con everywhere: true porta poi il browser a /oauth/logout dell’app Vimine, che chiude la sessione del socio e torna a postLogoutRedirectUri (default redirectUri; deve stare su un’origine registrata).

listener(session | null) a ogni accesso, rinnovo e uscita; con storage: 'local' anche per quelli avvenuti in altre schede. Restituisce la funzione per disiscriversi.

Una chiamata autenticata: Authorization: Bearer, JSON in entrata e in uscita, errori come VimineError, un nuovo tentativo dopo il rinnovo se la risposta è 401. init.idempotencyKey diventa l’header Idempotency-Key.

const events = await vimine.request('/v1/me/membership/events?limit=5');
Scope
me.get() profile:read il profilo (Me), con codicefiscale_check: come la persona è identificata (null = non ancora)
me.update(patch) profile:write telefono, genere, e l’identificazione: data, luogo e Stato di nascita (birth_country), codice fiscale — facoltativo, si può aggiungere più tardi. Un codice che non concorda risponde 422 con una voce codicefiscale_mismatch; se è confirmable, la persona lo conferma con codicefiscale_confirmed: true (guida)
Scope
membership.get() membership:read la tessera: status, verdict, expires_at, statuto, card
membership.request(body, { idempotencyKey? }) membership:request richiesta di tesseramento; chiave di idempotenza generata se assente. 422 identification_required se il profilo non è identificato: err.errors nomina ciò che manca, si completa con me.update()
membership.events({ limit?, cursor? }) membership:read storico degli stati, paginato
membership.statuto() membership:read lo statuto in vigore e l’accettazione del socio
membership.acceptStatuto({ version, sha256? }) statuto:accept registra l’accettazione
membership.card() membership:read il token della tessera (QR) e la sua finestra; 409 not_active se l’adesione non è attiva
membership.renew({ version, sha256? }) POST /v1/me/membership/renew rinnovo self-service: subito se gratuita senza approvazione, altrimenti richiesta alla segreteria
membership.setNetworkOptIn(bool) PATCH /v1/me/membership/network-opt-in consenso ai circuiti (network:manage)
membership.googleWalletUrl() GET /v1/me/membership/wallet/google link «Salva in Google Wallet»; 409 not_active se l’adesione non è attiva
membership.cardSvg() GET /v1/me/membership/card.svg la tessera come SVG (con QR); 409 not_active se l’adesione non è attiva
membership.emailCard() POST /v1/me/membership/card/email invia la tessera al socio per e-mail

Gli eventi pubblicati dall’associazione, compresi quelli riservati ai soci (events:read). Quelli pubblici non richiedono accesso: vimine.public.events.

events.list({ filter?, from?, to?, limit? }) filter: upcoming (predefinito), past, cancelled, all
events.get(slug) copia, immagini, tipi di iscrizione con posti rimanenti
events.eligibility(slug) il socio può iscriversi? per tipo, con le ragioni (membership_required, sold_out, …)

Le iscrizioni del socio (registrations:read / registrations:write). Vedi la guida Eventi e iscrizioni.

registrations.create(slug, { registration_type, note?, quantity? }, opts?) tipo gratuito → confirmed con il token del QR; con contributo → reserved con payment_instructions; 422 not_eligible con le ragioni; Idempotency-Key generata
registrations.list({ filter? }) · registrations.get(id) le iscrizioni del socio (filter: 'upcoming')
registrations.cancel(id) annulla entro la finestra dell’evento (409 window_closed oltre)
registrations.tokenPayload(id) il contenuto del QR di un’iscrizione confermata, o null
connections.list() le app che il socio ha autorizzato in questa associazione
connections.revoke(clientId) toglie il consenso a un’app (le sue sessioni terminano)

Gli endpoint pubblici, senza credenziali: vedi publicApi.

storage Dove Quando
'session' (default) sessionStorage: per scheda, sparisce chiudendola il default più sicuro per un client pubblico
'local' localStorage: condiviso tra schede, sopravvive al riavvio; l’uscita si propaga alle altre schede app in cui il socio si aspetta di restare connesso
'memory' solo in memoria SSR, test, chioschi
TokenStorage un tuo oggetto { get, set, remove } Node, storage cifrati, app native

Dove lo storage del browser non è disponibile (modalità privata, about:blank) l’SDK ripiega in memoria. MemoryStorage è esportata.

  • createPkce() → { verifier, challenge, method: 'S256' }, createVerifier(), createChallenge(verifier), createState(), base64url(bytes) — PKCE e state su WebCrypto, se costruisci il flusso a mano.
  • DEFAULT_API_URL, DEFAULT_APP_URL.
  • publicApi(options?) — vedi API pubblica.
  • VimineError — vedi Errori.