Introdução
O Easy Storage Manager é uma biblioteca JavaScript abrangente projetada para simplificar o gerenciamento de armazenamento no navegador. Ele oferece uma interface unificada para diferentes tipos de armazenamento, incluindo localStorage
, sessionStorage
, IndexedDB
, e cookies. Além disso, o Easy Storage Manager incorpora funcionalidades avançadas como compressão de dados usando um algoritmo baseado em LZW e criptografia segura utilizando a Web Crypto API (AES-GCM com PBKDF2).
Principais funcionalidades do Easy Storage Manager:
- Suporte para múltiplos backends de armazenamento (
localStorage
,sessionStorage
,IndexedDB
, cookies, e um fallback em memória). - Compressão de dados opcional para otimizar o uso de armazenamento (aplicável a IndexedDB e Cookies).
- Criptografia de dados opcional (AES-GCM) para garantir a segurança das informações armazenadas (aplicável a IndexedDB).
- Interface totalmente assíncrona (baseada em Promises) para melhor desempenho e compatibilidade.
- Sistema de eventos para monitorar operações como
set
,get
,remove
,clear
, eupdate
. - Operações utilitárias como incrementos, decrementos, manipulação de listas (
push
,pop
), e iteração (each
). - Sincronização entre instâncias, exportação e importação de dados.
- Facilidade de integração e configuração flexível através de um objeto de opções.
- Interface de gerenciamento visual (modal) opcional, acessível via tecla
F2
, para depuração, visualização e manipulação de dados em tempo real.
Características Principais
- Suporte Multi-Armazenamento: Interface unificada para
localStorage
,sessionStorage
,IndexedDB
, e cookies. - Compressão de Dados: Utiliza um algoritmo LZW para comprimir dados antes do armazenamento em IndexedDB (com ou sem criptografia) e Cookies, reduzindo o espaço utilizado. Deve ser habilitada via opções.
- Criptografia Segura: Implementa criptografia AES-GCM com PBKDF2 (SHA-256) via Web Crypto API para proteger dados em IndexedDB. Cookies não suportam criptografia.
- Interface Assíncrona: Todos os métodos retornam Promises, garantindo operações não bloqueantes.
- Eventos Personalizados: Permite escutar eventos como
set
,remove
,update
,clear
estorageTypeChange
. - Operações Avançadas: Suporte para
increment
,decrement
, manipulação de listas (push
,pop
), iteração (each
), e sincronização (sync
). - Configuração Flexível: Permite personalizar namespaces, tipo de armazenamento padrão, opções de criptografia, e configurações específicas para IndexedDB e Cookies.
- Exportação e Importação: Métodos
export
(para objeto) eimport
(de objeto) para migração e backup. - Interface de Gerenciamento Visual: Um modal de depuração opcional (ativado por
modalEnabled: true
ouenableModal(true)
) acessível viaF2
para visualizar, editar, gerenciar dados e ver analytics.
Instalação
Para usar o Easy Storage Manager, siga os passos abaixo:
1. Inclua o Script
Adicione o script JavaScript no seu HTML, preferencialmente antes do fechamento da tag </body>
:
<script src="https://cdn.alphasystem.dev/plugins/easy-storage-manager/latest/script-min.js"></script>
2. Inicialize a Biblioteca
O Easy Storage Manager não inicializa automaticamente. Você precisa criar uma instância da classe StorageManager
, passando um objeto de opções.
Inicialização Básica:
// Inicializa o Easy Storage Manager
const storage = new StorageManager({
namespace: 'myApp', // Prefixo para as chaves (recomendado)
storageType: 'localStorage' // 'localStorage', 'sessionStorage', 'indexedDB', 'cookies'
});
// Exemplo de uso após inicialização
async function saveData() {
try {
await storage.set('user', { id: 1, name: 'Anderson' });
console.log('Data saved!');
const user = await storage.get('user');
console.log('Retrieved user:', user);
} catch (error) {
console.error('Storage error:', error);
}
}
saveData();
Configuração Avançada (Exemplo):
const storage = new StorageManager({
namespace: 'secureApp',
storageType: 'indexedDB', // Usar IndexedDB
encrypt: true, // Habilitar criptografia (só funciona com IndexedDB)
cryptoPassword: 'uma_senha_muito_forte_e_secreta',
indexedDBOptions: {
dbName: 'SecureDatabase',
storeName: 'encryptedData',
dbVersion: 1
},
cookieOptions: { // Opções para quando storageType for 'cookies'
path: '/',
// domain: 'seusite.com', // Opcional
secure: true, // Recomendado para HTTPS
expires: 86400 // Expira em 1 dia (em segundos)
},
modalEnabled: true // Habilita a interface de gerenciamento (F2)
});
Nota sobre Compressão: A compressão não é uma opção global na inicialização. Ela é aplicada:
- Automaticamente em
IndexedDB
quando a criptografia (encrypt: true
) está habilitada. - Opcionalmente em
IndexedDB
(sem criptografia) passando{ compress: true }
nas opções do métodosetItem
. - Opcionalmente em
Cookies
secompress: true
for definido emcookieOptions
na inicialização, ou passando{ compress: true }
nas opções do métodosetItem
. localStorage
esessionStorage
não possuem compressão integrada pela biblioteca.
Configuração
O Easy Storage Manager é configurado através de um objeto de opções passado ao construtor new StorageManager(options)
. As principais opções são:
namespace
: (String) Um prefixo para todas as chaves armazenadas, ajudando a evitar conflitos. Padrão:'app'
.storageType
: (String) O tipo de armazenamento padrão a ser usado. Opções:'localStorage'
,'sessionStorage'
,'indexedDB'
,'cookies'
. Se o tipo escolhido não estiver disponível, ele tentará usar um fallback em memória. Padrão:'localStorage'
.encrypt
: (Boolean) Habilita a criptografia AES-GCM para os dados. Funciona apenas comstorageType: 'indexedDB'
. Se habilitado, a compressão também é aplicada automaticamente para IndexedDB. Padrão:false
.cryptoPassword
: (String) A senha usada para derivar a chave de criptografia via PBKDF2. Necessária seencrypt: true
. Padrão:'default_password'
.cookieOptions
: (Object) Opções específicas para quandostorageType: 'cookies'
. Contém sub-opções como:namespace
: (String) Usado como prefixo para nomes de cookies (sobrescreve o namespace global para cookies).compress
: (Boolean) Habilita compressão para cookies. Padrão:false
.encrypt
: (Boolean) Não suportado para cookies. Definir comotrue
causará um erro.expires
: (Number|Date) Tempo de expiração em segundos ou um objeto Date.path
: (String) Caminho do cookie. Padrão:'/'
.domain
: (String) Domínio do cookie.secure
: (Boolean) Define o atributo Secure do cookie. Padrão:false
.
indexedDBOptions
: (Object) Opções específicas para quandostorageType: 'indexedDB'
. Contém sub-opções como:dbName
: (String) Nome do banco de dados IndexedDB. Padrão:'StorageManagerDB'
.storeName
: (String) Nome do Object Store dentro do banco. Padrão:'keyval'
.dbVersion
: (Number) Versão do banco de dados. Padrão:1
.
modalEnabled
: (Boolean) Habilita a interface de gerenciamento visual (modal) acessível via teclaF2
. Padrão:false
.
Nota sobre Compressão (Reiterando): A compressão não é uma opção global. Veja a seção de Instalação para detalhes sobre como e quando ela é aplicada.
Exemplo de configuração personalizada:
const storage = new StorageManager({
namespace: 'meuApp',
storageType: 'indexedDB',
encrypt: true, // Criptografia para IndexedDB
cryptoPassword: 'senha_super_secreta',
indexedDBOptions: {
dbName: 'MeuBancoDeDados',
storeName: 'MinhaStore',
dbVersion: 2
},
cookieOptions: { // Configurações se usar 'cookies' futuramente
path: '/app',
secure: true,
expires: 3600, // 1 hora
compress: true // Habilitar compressão para cookies
},
modalEnabled: true // Habilitar modal de depuração (F2)
});
Uso e Integração
Após criar uma instância do StorageManager
, você pode usar seus métodos assíncronos para interagir com o armazenamento.
Operações Básicas (CRUD)
async function manageData() {
// Salvar um item (objeto)
await storage.set('userProfile', { name: 'Alice', theme: 'dark' });
// Salvar um item com expiração (10 minutos) e compressão (se aplicável)
await storage.set('tempData', 'valor_temporario', {
expire: 600000, // 10 minutos em milissegundos
compress: true // Tenta comprimir (funciona em Cookies/IndexedDB)
});
// Recuperar um item
const profile = await storage.get('userProfile');
console.log('Profile:', profile);
// Verificar se uma chave existe
const hasTemp = await storage.has('tempData');
console.log('Has tempData:', hasTemp);
// Remover um item
await storage.remove('tempData');
// Limpar todos os itens do namespace atual
// await storage.clear();
}
manageData();
Operações Numéricas e Listas
async function advancedOps() {
// Incrementar um contador (inicia em 0 se não existir)
const newCount = await storage.increment('pageViews', 1);
console.log('New page view count:', newCount);
// Decrementar
// await storage.decrement('itemsInCart', 1);
// Adicionar item a uma lista (cria a lista se não existir)
await storage.push('logMessages', { timestamp: Date.now(), msg: 'User logged in' });
// Remover e obter o último item da lista
const lastLog = await storage.pop('logMessages');
console.log('Last log message:', lastLog);
}
advancedOps();
Iteração, Exportação e Importação
async function dataMigration() {
// Iterar sobre todos os itens
await storage.each((key, value) => {
console.log(`Iterating: ${key} =`, value);
});
// Exportar todos os dados do namespace para um objeto
const allData = await storage.export();
console.log('Exported data:', JSON.stringify(allData));
// Importar dados de um objeto (sobrescreve existentes por padrão)
const dataToImport = {
settings: { lang: 'pt-BR' },
lastVisit: new Date().toISOString()
};
await storage.import(dataToImport, true); // true para sobrescrever
console.log('Data imported.');
}
dataMigration();
Eventos
// Escutar evento 'set'
storage.on('set', (key, value) => {
console.log(`Event: Key '${key}' was set/updated.`);
});
// Escutar evento 'remove'
storage.on('remove', (key) => {
console.log(`Event: Key '${key}' was removed.`);
});
// Escutar evento 'clear'
storage.on('clear', () => {
console.log('Event: Storage was cleared.');
});
// Escutar evento 'storageTypeChange'
storage.on('storageTypeChange', (newType) => {
console.log(`Event: Storage type changed to ${newType}.`);
});
// Remover um listener específico
// storage.removeListener('set', yourListenerFunction);
Outras Utilidades
async function utilities() {
// Obter número de chaves no namespace
const count = await storage.length();
console.log('Number of keys:', count);
// Obter uso de armazenamento (aproximado em bytes)
const usageBytes = await storage.getUsage();
console.log('Storage usage:', storage.formatBytes(usageBytes));
// Mudar o tipo de armazenamento em tempo de execução
// await storage.setStorageType('sessionStorage');
// Habilitar/Desabilitar o modal de depuração programaticamente
// storage.enableModal(true); // Habilita
// storage.enableModal(false); // Desabilita
}
utilities();
Interface de Gerenciamento (Modal)
Se modalEnabled: true
foi passado na configuração ou storage.enableModal(true)
foi chamado, pressione a tecla F2
para abrir a interface. Pressione F2
ou Esc
para fechar.
O modal permite:
- Visualizar dados em
localStorage
,sessionStorage
,cookies
, eIndexedDB
(selecionando DB/Store). - Filtrar chaves por nome.
- Adicionar novas entradas chave-valor.
- Editar valores existentes (incluindo JSON e booleanos).
- Excluir entradas individuais.
- Visualizar estatísticas de uso (Analytics), como número de operações, bytes usados, e última operação.
Referência da API
Construtor
new StorageManager(options?)
: Cria uma nova instância do gerenciador de armazenamento.
Parâmetros:
-options
(Object, opcional): Objeto de configuração (veja a seção 'Configuração').
Retorna: Instância deStorageManager
.
Métodos Principais (Assíncronos)
set(key, value, options?)
: Salva um item.
Parâmetros:
-key
(String): Chave.
-value
(Any): Valor (será JSON stringified internamente).
-options
(Object, opcional): Opções comoexpire
(Number, ms),compress
(Boolean, para Cookies/IndexedDB).
Retorna:Promise<void>
.get(key)
: Recupera um item.
Parâmetros:
-key
(String): Chave.
Retorna:Promise<any | null>
(valor parseado ounull
se não encontrado/expirado).remove(key)
: Remove um item.
Parâmetros:
-key
(String): Chave.
Retorna:Promise<void>
.clear()
: Limpa todos os itens do namespace atual.
Retorna:Promise<void>
.keys()
: Lista todas as chaves no namespace.
Retorna:Promise<string[]>
.has(key)
: Verifica se uma chave existe e não está expirada.
Parâmetros:
-key
(String): Chave.
Retorna:Promise<boolean>
.increment(key, by?)
: Incrementa um valor numérico.
Parâmetros:
-key
(String): Chave.
-by
(Number, opcional): Valor a incrementar. Padrão:1
.
Retorna:Promise<number>
(novo valor).decrement(key, by?)
: Decrementa um valor numérico.
Parâmetros:
-key
(String): Chave.
-by
(Number, opcional): Valor a decrementar. Padrão:1
.
Retorna:Promise<number>
(novo valor).push(key, value)
: Adiciona um valor ao final de uma lista (array).
Parâmetros:
-key
(String): Chave da lista.
-value
(Any): Valor a adicionar.
Retorna:Promise<void>
.pop(key)
: Remove e retorna o último valor de uma lista.
Parâmetros:
-key
(String): Chave da lista.
Retorna:Promise<any | null>
(valor removido ounull
se vazia/não for array).each(callback)
: Itera sobre todos os pares chave-valor no namespace.
Parâmetros:
-callback
(Function): Função(key, value) => void
chamada para cada item.
Retorna:Promise<void>
.export()
: Exporta todos os dados do namespace como um objeto.
Retorna:Promise<Object>
.import(data, overwrite?)
: Importa dados de um objeto.
Parâmetros:
-data
(Object): Objeto com pares chave-valor.
-overwrite
(Boolean, opcional): Setrue
, sobrescreve chaves existentes. Padrão:true
.
Retorna:Promise<void>
.sync(otherStorageManager)
: Importa dados de outra instânciaStorageManager
.
Parâmetros:
-otherStorageManager
(StorageManager): A instância de origem.
Retorna:Promise<void>
.length()
: Obtém o número de itens no namespace.
Retorna:Promise<number>
.setStorageType(type, options?)
: Altera o tipo de armazenamento em tempo de execução.
Parâmetros:
-type
(String): Novo tipo ('localStorage', 'sessionStorage', 'indexedDB', 'cookies').
-options
(Object, opcional): Novas opções para o tipo (ex:cookieOptions
,indexedDBOptions
).
Retorna:Promise<void>
.getUsage()
: Obtém o uso aproximado de armazenamento em bytes.
Retorna:Promise<number>
.
Métodos Síncronos
formatBytes(bytes, decimals?)
: Formata bytes em string legível (KB, MB, etc.).
Parâmetros:
-bytes
(Number): Número de bytes.
-decimals
(Number, opcional): Casas decimais. Padrão:2
.
Retorna:string
.enableModal(enable)
: Habilita ou desabilita o modal de depuração.
Parâmetros:
-enable
(Boolean):true
para habilitar,false
para desabilitar.
Retorna:void
.on(event, listener)
: Adiciona um listener de evento.
Parâmetros:
-event
(String): Nome do evento.
-listener
(Function): Callback.
Retorna:void
.removeListener(event, listener)
: Remove um listener.
Parâmetros:
-event
(String): Nome do evento.
-listener
(Function): Callback a remover.
Retorna:void
.once(event, listener)
: Adiciona um listener que executa apenas uma vez.
Parâmetros:
-event
(String): Nome do evento.
-listener
(Function): Callback.
Retorna:void
.emit(event, ...args)
: Dispara um evento manualmente (uso interno principalmente).
Retorna:void
.
Eventos Disponíveis (via on
, once
)
'set'
: Disparado apósset
. Callback recebe(key, value)
.'remove'
: Disparado apósremove
ou expiração noget
. Callback recebe(key)
.'clear'
: Disparado apósclear
. Callback não recebe argumentos.'update'
: Disparado quando um valor é alterado por outra aba/janela (via eventostorage
nativo). Callback recebe(key, newValue)
.'storageTypeChange'
: Disparado apóssetStorageType
. Callback recebe(newType)
.
Propriedades
namespace
(String): O namespace atual.storageType
(String): O tipo de armazenamento atual.analytics
(Object): Contém estatísticas de uso (setOperations
,getOperations
,removeOperations
,clearOperations
,totalBytesUsed
,lastOperation
).
Resolução de Problemas
Enfrentando problemas com o Easy Storage Manager? Aqui estão algumas soluções comuns:
StorageManager is not defined
: Verifique se o script foi incluído corretamente no HTML antes de tentar usarnew StorageManager(...)
.- Métodos não funcionam / Erros de Promise: Certifique-se de estar usando
await
ou.then()
com os métodos assíncronos (set
,get
,remove
, etc.). A inicialização também é assíncrona; a instância está totalmente pronta após oinitPromise
interno resolver. - Erros de Criptografia (IndexedDB): Verifique se a senha (
cryptoPassword
) está correta e consistente. A Web Crypto API requer um contexto seguro (HTTPS, localhost). Verifique o console do navegador por erros relacionados aSubtleCrypto
. - Erro
CookieStorage does not support encryption
: Você tentou usarencrypt: true
ou passou{ encrypt: true }
parasetItem
comstorageType: 'cookies'
. Remova a opção de criptografia para cookies. - Dados Não São Salvos/Recuperados: Verifique se o namespace está correto. Verifique os limites de armazenamento do navegador (especialmente para localStorage e cookies). Verifique se há erros no console. Se usando expiração (
expire
), certifique-se de que o item não expirou. - Compressão Não Funciona: Lembre-se que a compressão só é aplicável a IndexedDB e Cookies e precisa ser habilitada corretamente (veja seções de Instalação/Configuração). Não se aplica a localStorage/sessionStorage.
- Eventos Não São Disparados: Confirme que os listeners foram adicionados corretamente com
storage.on(...)
após a criação da instância. O eventoupdate
depende do eventostorage
nativo, que tem limitações (geralmente não dispara na mesma aba que fez a alteração). - Modal (F2) Não Abre: Verifique se
modalEnabled: true
foi passado na configuração ou sestorage.enableModal(true)
foi chamado. Verifique se há conflitos de teclas de atalho. Verifique o console por erros durante a inicialização do modal. - Problemas com IndexedDB: Erros podem ocorrer se a versão do banco (
dbVersion
) mudar ou se houver problemas ao abrir/criar o banco/store. Verifique o console por erros específicos de IndexedDB.
Se o problema persistir, verifique o console de desenvolvedor do navegador para mensagens de erro detalhadas e considere abrir uma issue no repositório do projeto (se disponível) ou contatar o suporte.
Exemplos de Código
Abaixo, exemplos práticos de uso do Easy Storage Manager:
Exemplo Básico (localStorage)
// 1. Inicialização
const storageLocal = new StorageManager({
namespace: 'meuAppLocal',
storageType: 'localStorage'
});
// 2. Uso
async function demoLocal() {
await storageLocal.set('username', 'Alice');
const user = await storageLocal.get('username');
console.log(`Usuário (localStorage): ${user}`);
}
demoLocal();
Exemplo com IndexedDB e Criptografia
// 1. Inicialização
const storageSecure = new StorageManager({
namespace: 'appSegura',
storageType: 'indexedDB',
encrypt: true,
cryptoPassword: 'senha_ultra_secreta_123',
indexedDBOptions: { dbName: 'DadosAppSeguro' }
});
// 2. Uso
async function demoSecure() {
await storageSecure.set('apiKey', 'xyz789-abc123-def456');
const key = await storageSecure.get('apiKey');
console.log(`API Key (IndexedDB Criptografado): ${key}`);
}
demoSecure();
Exemplo com Cookies, Compressão e Expiração
// 1. Inicialização
const storageCookie = new StorageManager({
namespace: 'cookieApp',
storageType: 'cookies',
cookieOptions: {
compress: true, // Habilitar compressão padrão para cookies
expires: 3600, // Expiração padrão de 1 hora
secure: true
}
});
// 2. Uso
async function demoCookie() {
// Salva com compressão e expiração padrão (1h)
await storageCookie.set('sessionData', { userId: 123, role: 'admin' });
// Salva outro cookie com expiração diferente (1 dia), sem compressão
await storageCookie.set('prefs', { theme: 'light' }, {
expires: 86400, // Sobrescreve expiração para 1 dia
compress: false // Sobrescreve compressão para false
});
const session = await storageCookie.get('sessionData');
console.log('Session (Cookie Comprimido):', session);
}
demoCookie();
Manipulando Listas e Números
async function demoListsNumbers() {
// Usando a instância 'storageLocal' do primeiro exemplo
// Adicionar itens a um log
await storageLocal.push('activityLog', 'Login');
await storageLocal.push('activityLog', 'Viewed Dashboard');
// Incrementar contador
const visits = await storageLocal.increment('siteVisits');
console.log(`Total de visitas: ${visits}`);
// Obter o log (será um array)
const log = await storageLocal.get('activityLog');
console.log('Activity Log:', log);
}
demoListsNumbers();
Exportando e Importando Dados
async function demoExportImport() {
// Usando a instância 'storageLocal'
await storageLocal.set('config', { lang: 'en', notifications: true });
// Exportar
const exportedData = await storageLocal.export();
console.log('Dados Exportados:', JSON.stringify(exportedData));
// Limpar para simular importação em outro lugar/tempo
// await storageLocal.clear();
// Importar
const dataToImport = { userPref: 'dark_mode', lastSync: '2023-10-27' };
await storageLocal.import(dataToImport);
console.log('Dados importados.');
const pref = await storageLocal.get('userPref');
console.log(`Preferência importada: ${pref}`);
}
demoExportImport();
Habilitando o Modal de Depuração
// Habilitar via configuração inicial:
const storageWithModal = new StorageManager({
namespace: 'debugApp',
modalEnabled: true
});
// Ou habilitar/desabilitar programaticamente:
// storageWithModal.enableModal(true); // Habilita
// Pressione F2 para abrir/fechar
// storageWithModal.enableModal(false); // Desabilita