Skip to content

Latest commit

 

History

History
234 lines (173 loc) · 7.94 KB

File metadata and controls

234 lines (173 loc) · 7.94 KB

encrypted-electron-store

npm version npm downloads License Issues Pull Requests


Simple encrypted data persistence for your Electron app - Save and load user settings, app state, cache, and more.

You can use it as a single store for both the main and renderer processes.


It has the same features as the well-known electron-store library, but solves several other things:

  • Encrypts the data saved on disk (using Electron's built-in safeStorage API)
  • Support for React hooks (auto re-renders view on store update)
  • Works in the renderer process (unlike electron-store - issue link)
  • Has CommonJS exports (electron-store has only ESM exports)
  • Uses the same API as zustand for getting values from store (via useEncryptedStore React hook)
    • e.g. const encrypted = useEncryptedStore(store => store.encrypted)

Install

npm i encrypted-electron-store
pnpm i encrypted-electron-store
yarn add encrypted-electron-store

Usage

Main process (main.ts/js)

import EncryptedStore from 'encrypted-electron-store/main'

const store = EncryptedStore.create<any>()
// or: const store = EncryptedStore.create<{ encrypted: string }>()
// or: const store = EncryptedStore.create<IStore>()

store.set('encrypted', '🔒')
console.log(store.get('encrypted'))
//=> '🔒'

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

// IMPORTANT: If you want to use the store in the renderer process
window.webContents.on('did-finish-load', () => {
	encryptedStore.setBrowserWindow(window)
})

Renderer process

If you want to use this library in the renderer process, you first need to call this function in the preload.ts/js file.

// preload.ts/js
import { preloadEncryptedStore } from 'encrypted-electron-store/preload'

preloadEncryptedStore()

// ... rest of the file

React

Add the EncryptedStoreProvider component in main.tsx/jsx or wherever you want in your React project.

// main.tsx/jsx
import { EncryptedStoreProvider } from 'encrypted-electron-store/react'

ReactDOM.createRoot(document.getElementById("root")!).render(
  <React.StrictMode>
    <EncryptedStoreProvider>
      <App />
    </EncryptedStoreProvider>
  </React.StrictMode>
);

Use the useEncryptedStore() hook wherever you want in your React project.

// e.g. App.tsx/jsx
import { useEncryptedStore } from 'encrypted-electron-store/react'

function App() {
  const { store, setStore } = useEncryptedStore<{ encrypted: string }>()
  const encrypted = useEncryptedStore<{ encrypted: string }>((store) => store.encrypted);

  setStore({ encrypted: '🔒' });

  return (
    /* Gets automatically re-rendered when the value changes */
    <p>{encrypted}</p>
  )
}

Vanilla JS

import EncryptedStore from 'encrypted-electron-store/vanilla'

// You need to use `await` because the library reads the initial store from the file on disk.
const store = await EncryptedStore.create<{ encrypted: string }>()

store.set('encrypted', '🔒')
console.log(store.get('encrypted'))
// => '🔒'

Docs

You can find examples of usage in real projects in the examples folder.

todo: Here will be specified detailed documentation; or just link to the official docs

Contribution

  1. Clone this repo:
git clone https://github.com/rixcian/encrypted-electron-store
  1. Make sure you have node v22:
nvm use
  1. Install dependencies:
npm i
  1. After making changes, run tests:
npm run test
  1. Create changelog:
npx @changesets/cli
  1. As a maintainer, after review, I will run:
npx @changesets/cli version
  1. Build the library:
npm run build
  1. And publish it to NPM with:
npx @changesets/cli publish

Comparison to electron-store

Feature encrypted-electron-store electron-store
Works in main & renderer processes ✅ Yes 🟡 Only in main process
ESM & CommonJS exports ✅ ESM & CJS Supported ❌ Only ESM exports supported
Encryption ✅ Uses Electron's built-in encryption 🟡 Not sufficient (encryption password in plaintext)
React Integration ✅ Built-in React hooks ❌ No React integration
Vanilla JS Integration ✅ Simple API ✅ Simple API
File Extensions ✅ Configurable ✅ Configurable
Works with files atomically ✅ Yes ✅ Yes
JSON Schema validation 🟡 Work in progress ✅ Yes
Migrations ❌ Yes, if there'll be demand 🟡 Yes, with bugs (more info)

Todos

  • Finish basic React implementation
  • Make const time = useEncryptedStore((store, setStore) => store.time) architecture possible (similar to zustand)
// Usage
const { store, setStore } = useEncryptedStore<Store>()
const time = useEncryptedStore<Store>((store) => store.time)
const setStore = useEncryptedStore<Store>((_, setStore) => setStore)

// Another possible usage
const { store, setStore } = useEncryptedStore<Store>()
const { time, setStore } = useEncryptedStore<Store>((store, setStore) => ({
	time: store.time,
	setStore,
}))