Armazenamento de dados simples e preferências de usuário no Electron com electron-store

1 https://github.com/sindresorhus/electron-store

O Electron não fornece mecanismos nativos para armazenar preferências e outros dados. O módulo electron-store resolve esse problema, permitindo que você se concentre na construção da aplicação. Os dados são salvos em um arquivo JSON localizado em app.getPath('userData')2. Este módulo pode ser utilizado diretamente tanto no processo principal quanto no processo de renderização.

2 https://electronjs.org/docs/api/app#appgetpathname

app.getPath(name) — Pasta onde os arquivos de configuração da sua aplicação são armazenados, por padrão é a pasta appData seguida pelo nome da aplicação.

  • appData — Pasta de dados da aplicação do usuário atual, por padrão corresponde a:
    • %APPDATA% no Windows
    • $XDG_CONFIG_HOME ou ~/.config no Linux
    • ~/Library/Application Support no macOS

Por que não usar window.localStorage?

  1. localStorage funciona apenas dentro do processo do navegador (renderizador).
  2. A tolerância a falhas do localStorage é limitada, o que pode resultar em perda de dados se a aplicação falhar inesperadamente.
  3. O localStorage suporta apenas strings persistentes. Este módulo permite qualquer tipo suportado pelo JSON.
  4. O localStorage apresenta riscos de segurança, podendo ser explorado por ataques XSS.
  5. A API do electron-store é mais robusta. Permite definir e acessar propriedades aninhadas. Também permite configurar valores padrão iniciais.

Diferenças entre Vuex e Storage

  1. O Vuex armazena dados em memória, enquanto o localStorage salva em arquivos locais. Os dados do electron-store permanecem após o fechamento da aplicação.
  2. Caso de uso: Vuex é usado para comunicação entre componentes; localStorage é ideal para compartilhar dados entre páginas.
  3. Persistência: ao recarregar a página, os dados do Vuex são perdidos, mas os do localStorage continuam disponíveis.

Nota: Muitos desenvolvedores consideram o localStorage uma alternativa ao Vuex. Para dados imutáveis, isso pode funcionar. Porém, quando dois componentes compartilham uma mesma fonte de dados (objeto ou array), e um altera o valor esperando que o outro reaja, o localStorage falha nessa tarefa, conforme explicado no item 1.

Instalando o electron-store

$ npm install electron-store

Nota: Requer Electron 5 ou superior. Em caso de falha na instalação, utilize o comando cnpm install electron-store (desde que o cnpm esteja instalado).

Uso básico do electron-store

const Store = require('electron-store');

const store = new Store();

store.set('unicorn', '🦄');
console.log(store.get('unicorn'));
//=> '🦄'

// Acessando propriedades aninhadas com notação por ponto
store.set('foo.bar', true);
console.log(store.get('foo'));
//=> {bar: true}

store.delete('unicorn');
console.log(store.get('unicorn'));
//=> undefined

API do electron-store

As alterações são gravadas atomicamente no disco, garantindo que, mesmo que o processo falhe durante a escrita, a configuração existente não seja corrompida.

1. Store(options?)

Retorna: Uma nova instância.

Opções

defaults

Tipo: object

Valores padrão para os itens do armazenamento. Nota: Valores padrão sobrescrevem as chaves padrão definidas no esquema.

schema

Tipo: object

O JSON Schema3 define restrições para dados JSON. Com ele, partes envolvidas podem entender e validar dados, assegurando integridade na troca. A versão mais recente é a draft 7, publicada em 2018-03-19.

3 https://json-schema.org/

Internamente, o validador ajv4 é usado para verificar o esquema. Utilizamos a draft-07 do JSON Schema e oferecemos suporte completo a keywords de validação5 e formatos6.

4 https://github.com/epoberezkin/ajv
5 https://github.com/epoberezkin/ajv/blob/master/KEYWORDS.md
6 https://github.com/epoberezkin/ajv#formats

Exemplo:

const Store = require('electron-store');

const schema = {
	foo: {
		type: 'number',
		maximum: 100,
		minimum: 1,
		default: 50
	},
	bar: {
		type: 'string',
		format: 'url'
	}
};

const store = new Store({schema});
console.log(store.get('foo'));
//=> 50

store.set('foo', '1');
// [Error: Config schema violation: `foo` should be number]

Nota: Valores padrão serão substituídos se forem definidos.

migrations

Tipo: object

Nota: Não use esta funcionalidade antes de reoslver o problema7.

Permite executar operações no armazenamento ao atualizar a versão. O objeto deve conter pares de chave-valor com versões e funções de tratamento. As versões podem ser ranges semver8. Exemplo:

7 https://github.com/sindresorhus/conf/issues/92
8 https://github.com/npm/node-semver#ranges

const Store = require('electron-store');

const store = new Store({
	migrations: {
		'0.0.1': store => {
			store.set('debugPhase', true);
		},
		'1.0.0': store => {
			store.delete('debugPhase');
			store.set('phase', '1.0.0');
		},
		'1.0.2': store => {
			store.set('phase', '1.0.2');
		},
		'>=2.0.0': store => {
			store.set('phase', '>=2.0.0');
		}
	}
});

name

Tipo: string
Padrão: config

Nome do arquivo de armazenamento (sem extensão).

Útil para múltiplos arquivos de configuração ou módulos reutilizáveis.

cwd

Tipo: string
Padrão: app.getPath('userData')

Localização do arquivo de armazenamento. Evite especificar, a menos que necessário. Por padrão, segue as convenções do sistema. Caminhos relativos são relativos ao diretório padrão.

encryptionKey

Tipo: string | Buffer | TypedArray | DataView
Padrão: undefined

Usado para proteger dados sensíveis. Pode também servir para ofuscar o conteúdo do arquivo. Ao fornecer uma chave, o arquivo será criptografado com aes-256-cbc.

fileExtension

Tipo: string
Padrão: json

Extensão do arquivo de configuração. Útil para interagir com arquivos customizados.

clearInvalidConfig

Tipo: boolean
Padrão: true

Se o arquivo de configuração tiver erro de sintaxe, ele será limpo. Útil para evitar configurações corrompidas. Desative se quiser que erros sejam lançados em vez de limpar.

serialize

Tipo: Function
Padrão: value => JSON.stringify(value, null, '\t')

Função usada para serializar objetos em string UTF-8 ao escrever. Útil se quiser formatos além do JSON.

deserialize

Tipo: Function
Padrão: JSON.parse

Função usada para desserializar strings UTF-8 ao ler. Útil se quiser formatos além do JSON.

accessPropertiesByDotNotation

Tipo: boolean
Padrão: true

Permite acesso a propriedades aninhadas com notação por ponto.

const Store = require('electron-store');

const store = new Store();
store.set({
	foo: {
		bar: {
			foobar: '🦄'
		}
	}
});
console.log(store.get('foo.bar.foobar'));
//=> '🦄'

Se desativado, o caminho inteiro é tratado como uma única chave.

const store = new Store({accessPropertiesByDotNotation: false});
store.set({
	`foo.bar.foobar`: '🦄'
});
console.log(store.get('foo.bar.foobar'));
//=> '🦄'

watch

Tipo: boolean
Padrão: false

Monitora mudanças no arquivo de configuração. Útil quando múltiplos processos modificam o mesmo arquivo. Não funciona no Node.js 8 no macOS.

2. Instância

Você pode usar notação por ponto para acessar propriedades aninhadas. A instância é iterável, podendo ser usada diretamente em laços for...of.

  • .set(key, value) — Define um item. O valor deve ser serializável em JSON.
  • .set(object) — Define múltiplos itens.
  • .get(key, [defaultValue]) — Obtém um item ou o valor padrão.
  • .reset(...keys) — Restaura valores padrão.
  • .has(key) — Verifica se um item existe.
  • .delete(key) — Remove um item.
  • .clear() — Remove todos os itens.
  • .onDidChange(key, callback) — Monitora mudanças em uma chave específica.
  • .onDidAnyChange(callback) — Monitora todas as mudanças no objeto de configuração.
  • .size — Retorna o número total de itens.
  • .store — Obtem ou substitui todos os dados.
  • .path — Caminho do arquivo de armazenamento.
  • .openInEditor() — Abre o arquivo no editor do usuário.

FAQ

Posso usar YAML ou outro formato de serialização?

Sim, desde que a representação seja compatível com codificação utf8. Exemplo com YAML:

const Store = require('electron-store');
const yaml = require('js-yaml');

const store = new Store({
	fileExtension: 'yaml',
	serialize: yaml.safeDump,
	deserialize: yaml.safeLoad
});

Recursos relacionados

  1. electron-util – Utilitários úteis para desenvolvimento de aplicações Electron
  2. electron-debug – Adiciona recursos de depuração à sua aplicação Electron
  3. electron-context-menu – Menu de contexto para aplicações Electron
  4. electron-dl – Download simplificado de arquivos em aplicações Electron
  5. electron-unhandled – Trata erros não tratados em aplicações Electron
  6. electron-reloader – Recarregamento automático durante o desenvolvimento
  7. electron-serve – Serviço de arquivos estáticos para aplicações Electron
  8. conf – Gerenciamento simples de configurações

Artigo original: https://xushanxiang.com/2019/12/electron-store.html

Tags: Electron electron-store javascript JSON storage

Publicado em 8-29 20:33