npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

vuex-electron-store-vue3

v2.0.2

Published

Persist and rehydrate the Vuex state in your Electron app

Downloads

3

Readme

💾 Vuex Electron Store

Persist and rehydrate the Vuex state in your Electron app.

Checkout some of the great work we are doing @Singular Health

Features

  • 💾 Persistent state - persistently stores the Vuex state in your Electron app
  • 🔌 Easy integration - integrates perfectly with Vue and Electron as a Vuex Plugin
  • 🔨 Customization - specify what parts of your Vuex state you want to persist and which mutations are allowed
  • ♻️ Migrations - the persisted state can be easily migrated between different versions of your Electron app
  • 🔐 Encryption - you can optionally encrypt the storage file with a encryption key
  • ⚙️ Electron main process - access the state & commit mutations/dispatch actions from the Electron main process

This library is a wrapper around electron-store to make it work directly with Vuex and offer additional features.

🚀 Get started

npm install vuex-electron-store-vue3

Requires Electron 26 or later and works with Vue 3

📚 Usage

To use vuex-electron-store-vue3, add it as a plugin to your Vuex store:

import Vue from 'vue'
import Vuex from 'vuex'

import PersistedState from 'vuex-electron-store-vue3'

Vue.use(Vuex)

export default new Vuex.Store({
	// ...
	plugins: [
		PersistedState.create()
	],
	// ...
})

And then initialize it in the Electron main process:

import PersistedState from 'vuex-electron-store-vue3'

PersistedState.initRenderer()

If you access the store from the main process (using .getStoreFromRenderer(ipcMain)) this is not needed

And you are done! Your Electron app now has a persistent Vuex state! 🎉

⚙️ Options

You can also pass an options object to .create() to customize the behaviour of vuex-electron-store-vue3 further:

PersistedState.create({
	paths: [ 'auth.user' ]
})

| Name | Type | Description | Default | | ------------- | ------------- |----------------------------------------------------------------------------------------------------------------| ------------- | | fileName | string | Name of the storage file (without extension) | vuex | | paths | array | An array of any paths to partially persist the state | n/a | | filter | function | A function which will be called on each mutation that triggers setState | n/a | | overwrite | boolean | Overwrite the existing state with the persisted state directly when rehydrating | false | | storageKey | string | Name of the key used for the stored state object | state | | checkStorage | boolean | Check if the storage file is available and can be accessed | true | | dev | boolean | Enable development mode | false | | reducer | function | A function to reduce the state to persist based on the given paths | n/a | | arrayMerger | function | A function for merging arrays when rehydrating state | combine arrays | | resetMutation | string | Name of a mutation which when called will reset the persisted state | n/a | | encryptionKey | string/Buffer/TypedArray/DataView | Encryption key used to encrypt the storage file | n/a | | storageFileLocation | string | Location where the storage file should be stored | config directory | | migrations | object | Migration operations to perform to the persisted state whenever a version is upgraded | n/a | | ipc | boolean | Enable IPC communication with the main process (ensure you pass the ipcRenderer object to the secondary param) | false |

🛠️ Configuration

Here are some of the more important options in a more detailed form.

Paths

You can specify different paths (i.e. parts) of you state with the paths option. It accepts an array of paths specified using dot notation e.g. user.name.

If no paths are given, the complete state is persisted. If an empty array is given, no state is persisted.

PersistedState.create({
	paths: ['user.token']
})

Here, only the user.token will be persisted and rehydrated.


Filter

You can limit the mutations which can persist state with the filter function. The specified function will be called on each mutation that triggers setState.

PersistedState.create({
	filter: (name) => name === 'increment'
})

Here, only state changed by the increment mutation will be persisted and rehydrated.


Overwrite

By default the the existing state will be merged using deepmerge with the persisted state. If you set overwrite to true, the persisted state will overwrite the existing state directly when rehydrating.

PersistedState.create({
	overwrite: true
})

Development Mode

During development it might be useful to disable persisting and rehydrating the state. You can disable this with the dev option. When it is set to true, all changes to the state will not be persisted (regardless of the paths provided), rehydration of the state will be skipped and migrations will not be performed.

PersistedState.create({
	dev: true
})

Migrations

You can specify operations to perform to the persisted state whenever a version is upgraded. The migrations object should consist of a key-value pair of 'version': handler (the version can also be a semver range). In the handler you can manipulate the previously persisted state (just like any other JavaScript object) before it is rehydrated.

PersistedState.create({
	migrations: {
		'0.1.0': (state) => {
			state.debugPhase = true
		},
		'1.0.0': (state) => {
			delete state.debugPhase
			state.phase = '1.0.0'
		},
		'1.0.2': (state) => {
			state.phase = '1.0.2'
		},
		'>=2.0.0': (state) => {
			state.phase = '>=2.0.0'
		}
	}
})

The state parameter contains the persisted state before rehydration.


Reset Mutation

You can programmatically reset the persisted state by specifying the name of a mutation as the resetMutation option. Once you call that mutation, the entire persisted state will be deleted. You have to create a mutation by the same name, even if it doesn't do anything.

PersistedState.create({
	resetMutation: 'ELECTRON_STORE_RESET'
})

You have to create a mutation by the same name, even if it doesn't do anything.:

mutations: {
	ELECTRON_STORE_RESET(state) {
		// Optionally do something else here
	}
}	

Later in a component or somewhere else:

this.$store.commit('ELECTRON_STORE_RESET')

Encryption

You can optionally specify an encryption key which will be used to encrypt the storage file using the aes-256-cbc encryption algorithm. This is only secure if you don't store the key in plain text, but in a secure manner in the Node.js app. You could use node-keytar to store the encryption key securely, or deriving the key from a password entered by the user.

It might also be useful for obscurity. If a user looks through the config directory and finds the config file, since it's just a JSON file, they may be tempted to modify it. By providing an encryption key, the file will be obfuscated, which should hopefully deter any users from doing so.

PersistedState.create({
	encryptionKey: 'superSecretKey'
})

Don't store the key like this if security is of concern, the encryption key would be easily found in the Electron app.


IPC Mode

If you want to access the state or commit mutations/dispatch actions from the Electron main process, you need to enable ipc mode.

You can then use the .getStoreFromRenderer(ipcMain) method in the main process to listen for an IPC connection from the renderer. Once connected you can use the returned .commit() and .dispatch() methods like you would in a normal Vue Component. Calling .getState() returns a promise containing the current Vuex state.

This can only be used with one renderer

Enable ipc mode:

import { ipcRenderer } from 'electron';

PersistedState.create({
	ipc: true
}, ipcRenderer)

Then in the Electron main process:

import PersistedState from 'vuex-electron-store-vue3'
import { ipcMain } from 'electron'

const store = await PersistedState.getStoreFromRenderer(ipcMain)

// Commit a mutation
store.commit(type, payload, options)

// Dispatch an action
store.dispatch(type, payload, options)

// Get the current Vuex State
const state = await store.getState()

// Reset the persisted State
store.clearState()

When you use .getStoreFromRenderer(ipcMain) you don't need to call .initRenderer()


📖 Examples

Here are a few examples to help you get started!

Before you use any of them, make sure you initialize the module in the Electron main process:

import PersistedState from 'vuex-electron-store-vue3'

PersistedState.initRenderer()

Basic Example

In this example the entire state will be persisted and rehydrated after a restart:

import Vue from 'vue'
import Vuex from 'vuex'

import PersistedState from 'vuex-electron-store-vue3'

Vue.use(Vuex)

export default new Vuex.Store({
	// ...
	state: {
		username: ''
	},
	plugins: [
		PersistedState.create()
	],
	// ...
})

Only partially persist state

In this example only part of the state will be persisted and rehydrated after a restart:

import Vue from 'vue'
import Vuex from 'vuex'

import PersistedState from 'vuex-electron-store-vue3'

Vue.use(Vuex)

export default new Vuex.Store({
	// ...
	state: {
		input: ''
		user: {
			token: ''
		}
	},
	plugins: [
		PersistedState.create({
			paths: ['user.token']
		})
	],
	// ...
})

Here, only the user.token will be persisted and rehydrated.


Filter mutations

In this example we add a filter to specify which mutations can persist the updated state:

import Vue from 'vue'
import Vuex from 'vuex'

import PersistedState from 'vuex-electron-store-vue3'

Vue.use(Vuex)

export default new Vuex.Store({
	// ...
	mutations: {
		// ...
		increment(state) {
			// mutate state
			state.count++
		},
		decrement(state) {
			// mutate state
			state.count--
		}
	},
	plugins: [
		PersistedState.create({
			filter: (name) => name === 'increment'
		})
	],
	// ...
})

Here, only state changed by the increment mutation will be persisted and rehydrated.


Merging arrays

By default arrays from the existing state will be merged with arrays from the persisted state. You can change this behaviour by specifying a different arrayMerger function which deepmerge will use to merge the two arrays.

import Vue from 'vue'
import Vuex from 'vuex'

import PersistedState from 'vuex-electron-store-vue3'

Vue.use(Vuex)

export default new Vuex.Store({
	// ...
	state: {
		todos: ['test1', 'test2']
	},
	plugins: [
		PersistedState.create({
			arrayMerger: (stateArray, persistedStateArray, options) => { /* ... */ }
		})
	],
	// ...
})

Use the function below to overwrite the existing arrays with the persisted arrays:

const overwriteMerge = (stateArray, persistedStateArray, options) => persistedStateArray

If you want to overwrite the entire state, not just arrays, set the overwrite option to true instead.


Overwriting the existing state

By default the existing state will be merged with the persisted state using deepmerge. You can disable this behaviour and instead directly overwrite the existing state with the persisted state using the overwrite option:

import Vue from 'vue'
import Vuex from 'vuex'

import PersistedState from 'vuex-electron-store-vue3'

Vue.use(Vuex)

export default new Vuex.Store({
	// ...
	plugins: [
		PersistedState.create({
			overwrite: true
		})
	],
	// ...
})

During development

Setting dev to true will stop vuex-electron-store-vue3 from persisting and rehydrating the state.

import Vue from 'vue'
import Vuex from 'vuex'

import PersistedState from 'vuex-electron-store-vue3'

Vue.use(Vuex)

export default new Vuex.Store({
	// ...
	plugins: [
		PersistedState.create({
			dev: true
		})
	],
	// ...
})

Reset Mutation

You can reset the persisted state by specifying a mutation as the resetMutation option and then calling it:

import Vue from 'vue'
import Vuex from 'vuex'

import PersistedState from 'vuex-electron-store-vue3'

Vue.use(Vuex)

export default new Vuex.Store({
	// ...
	mutations: {
		ELECTRON_STORE_RESET(state) {
			// Optionally do something else here
		}
	},
	plugins: [
		PersistedState.create({
			resetMutation: 'ELECTRON_STORE_RESET'
		})
	],
	// ...
})

// Later in a component or somewhere else
this.$store.commit('ELECTRON_STORE_RESET')

You have to create a mutation by the same name, even if it doesn't do anything.


Encrypting the storage file

You can optionally encrypt/obfuscate the storage file by specifying an encryption key:

import Vue from 'vue'
import Vuex from 'vuex'

import PersistedState from 'vuex-electron-store-vue3'

Vue.use(Vuex)

export default new Vuex.Store({
	// ...
	plugins: [
		PersistedState.create({
			encryptionKey: 'superSecretKey'
		})
	],
	// ...
})

Don't store the key like this if security is of concern, the encryption key would be easily found in the Electron app.


Migration between versions

You can use migrations to perform operations on the persisted data whenever a version is upgraded. The migrations object should consist of a key-value pair of 'version': handler. In the handler you can manipulate the state like any other JavaScript object:

import Vue from 'vue'
import Vuex from 'vuex'

import PersistedState from 'vuex-electron-store-vue3'

Vue.use(Vuex)

export default new Vuex.Store({
	// ...
	plugins: [
		PersistedState.create({
			migrations: {
				'0.1.0': (state) => {
					state.debugPhase = true
				},
				'1.0.0': (state) => {
					delete state.debugPhase
					state.phase = '1.0.0'
				},
				'1.0.2': (state) => {
					state.phase = '1.0.2'
				},
				'>=2.0.0': (state) => {
					state.phase = '>=2.0.0'
				}
			}
		})
	],
	// ...
})

The state parameter contains the persisted state before rehydration.

Access the store from the Electron main process

If you enable the ipc mode you can access the state or commit mutations/dispatch actions from the Electron main process:

import PersistedState from 'vuex-electron-store-vue3'
import { ipcMain } from 'electron';

const store = await PersistedState.getStoreFromRenderer(ipcMain)

// Commit a mutation
store.commit(type, payload, options)

// Dispatch an action
store.dispatch(type, payload, options)

// Get the current Vuex State
const state = await store.getState()

// Reset the persisted State
store.clearState()

When you use .getStoreFromRenderer(ipcMain) you don't need to call .initRenderer()


💻 Development

Issues and PRs are very welcome!

  • run yarn lint or npm run lint to run eslint.
  • run yarn watch or npm run watch to watch for changes.
  • run yarn build or npm run build to produce a compiled version in the lib folder.

❔ About

This project was originally developed by (@betahuhn) in their free time, and has been updated to work with Vue3 by (@elliottcooper) on behalf of (Singular Health).

Credit

This library is a wrapper around the great electron-store by @sindresorhus and was inspired by vuex-electron and vuex-persistedstate. This project was originally developed by (@betahuhn).

📄 License

Copyright 2023 Elliott Cooper (Singular Health)

This project is licensed under the MIT License - see the LICENSE file for details.