Vimine (browser)
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.
Opzioni
Sezione intitolata “Opzioni”| 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.
Accesso
Sezione intitolata “Accesso”signIn(options?)
Sezione intitolata “signIn(options?)”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 |
createSignInUrl(options?)
Sezione intitolata “createSignInUrl(options?)”Costruisce l’URL di autorizzazione e memorizza l’accesso in corso (verifier PKCE e state), senza navigare.
Utile se vuoi rendere tu il link.
hasRedirectParams(url?)
Sezione intitolata “hasRedirectParams(url?)”true se l’URL (default: la pagina corrente) porta i parametri di un ritorno (code+state oppure error).
handleRedirect({ url?, cleanUrl? })
Sezione intitolata “handleRedirect({ url?, cleanUrl? })”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.
Sessione
Sezione intitolata “Sessione”getSession() · isSignedIn()
Sezione intitolata “getSession() · isSignedIn()”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}getAccessToken()
Sezione intitolata “getAccessToken()”Un access token valido, rinnovato se scade entro 30 secondi. Lancia not_signed_in senza sessione.
refresh()
Sezione intitolata “refresh()”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).
onChange(listener)
Sezione intitolata “onChange(listener)”listener(session | null) a ogni accesso, rinnovo e uscita; con storage: 'local' anche per quelli avvenuti in
altre schede. Restituisce la funzione per disiscriversi.
API del socio
Sezione intitolata “API del socio”request(path, init?)
Sezione intitolata “request(path, init?)”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) |
membership
Sezione intitolata “membership”| 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, …) |
registrations
Sezione intitolata “registrations”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
Sezione intitolata “connections”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
Sezione intitolata “Storage”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.
Utilità
Sezione intitolata “Utilità”createPkce()→{ verifier, challenge, method: 'S256' },createVerifier(),createChallenge(verifier),createState(),base64url(bytes)— PKCE estatesu WebCrypto, se costruisci il flusso a mano.DEFAULT_API_URL,DEFAULT_APP_URL.publicApi(options?)— vedi API pubblica.VimineError— vedi Errori.