Storage
Onde o client de navegador guarda a sessão, e como mudar isso.
O client de navegador persiste a sessão para que um reload não desautentique a pessoa. Qual meio ele usa é escolha sua.
Sem a opção storage, ele usa Storage.Local quando window existe, e um
armazenamento em memória do próprio client em qualquer outro lugar. Um módulo de
client que também é avaliado na renderização no servidor nunca toca o
localStorage, e dois clients criados no servidor nunca compartilham sessão.
import { createClient, Storage } from '@nulvless/nulvless-js';
createClient(url, key, { storage: Storage.Local });Só no navegador. O createServerClient não tem armazenamento de sessão — um
servidor não guarda a sessão de um usuário específico, então storage e
storageKeys não fazem parte de ServerClientOptions.
Os adaptadores
Storage.LocallocalStorageOptionalSobrevive a reloads e a reinícios do navegador.
Storage.SessionsessionStorageOptionalLimpo quando a aba ou o navegador fecha.
Storage.MemoryMapOptionalPerdido no reload. Uma única instância compartilhada por todo client que a
usa — crie um new MemoryStorageAdapter() quando cada client precisar do seu.
Storage.CacheCache Storage APIOptionalSobrevive a reloads, e é alcançável a partir de service workers.
Escolher entre eles é uma decisão de produto, não técnica:
- Local mantém as pessoas autenticadas entre visitas. É o que a maioria das aplicações quer.
- Session desautentica quando a aba fecha. Máquinas compartilhadas, produtos de risco mais alto.
- Memory não persiste nada — o correto no servidor, e em testes onde vazar estado entre casos é pior do que autenticar de novo.
- Cache é para quando um service worker também precisa da sessão.
Chaves
Duas entradas são escritas, e os dois nomes de chave podem ser trocados:
createClient(url, key, {
storageKeys: {
token: 'my-app-token',
accounts: 'my-app-accounts',
},
});O padrão é nlv-<slug>-token e nlv-<slug>-token-accounts. A entrada
accounts só importa com multi-conta
habilitado.
Um adaptador próprio
Qualquer objeto com estes três métodos funciona:
interface NulvlessStorage {
getItem(key: string): Promise<string | null>;
setItem(key: string, value: string): Promise<void>;
removeItem(key: string): Promise<void>;
}Os três são assíncronos, então um adaptador apoiado em IndexedDB, num cofre nativo do sistema ou num wrapper criptografado encaixa sem o SDK perceber diferença:
const encrypted: NulvlessStorage = {
async getItem(key) {
const raw = await SecureStore.getItemAsync(key);
return raw ? decrypt(raw) : null;
},
async setItem(key, value) {
await SecureStore.setItemAsync(key, encrypt(value));
},
async removeItem(key) {
await SecureStore.deleteItemAsync(key);
},
};
createClient(url, key, { storage: encrypted });