electron-conf
Simple data persistence for your Electron app - save and load user settings, app state, cache, etc
Another electron-store, minimal fork of conf, with more features.
electron-conf is a fork of conf (behind electron-store). What we try to achieve in this library, is to eliminate some dependencies and features that our target users don't need, and is designed only for Electron.
- ✅ Minimal and simple
- ✅ Read data form disk once, ~100x faster
- ✅ Simpler migration strategy
- ✅ Safer to use it in Electron renderer (no nodeIntegration)
- ✅ Written in TypeScript, and support CommonJS and ESM. For Electron 13.x and higher.
- ❌ No watch
- ❌ No encryption
If you need features like watch or encryption, electron-store is a better choice for you.
Install
$ npm install electron-conf
Usage
Using in Electron Main Process
import { Conf } from 'electron-conf/main'
const conf = new Conf()
conf.set('foo', '🌈')
console.log(conf.get('foo'))
conf.set('a.b', true)
console.log(conf.get('a'))
conf.delete('foo')
console.log(conf.get('foo'))
Using in Electron Renderer Process
- Register a listener in main process, so that you can use it in the renderer process.
import { Conf } from 'electron-conf/main'
const conf = new Conf()
conf.registerRendererListener()
- Expose the
Conf
API.
You can expose it in the specified preload script:
import { exposeConf } from 'electron-conf/preload'
exposeConf()
Or, you can expose it globally in the main process for all renderer processes:
import { useConf } from 'electron-conf/main'
useConf()
- Use it in the renderer process
import { Conf } from 'electron-conf/renderer'
const conf = new Conf()
await conf.set('foo', 1)
[!NOTE]
Use the same way as the main process. The difference is that all APIs are promise-based.
API
Conf([options])
return a new instance.
[!WARNING]
It does not support multiple instances reading and writing the same configuration file.
Constructor Options
[!NOTE] > Conf
for the renderer process, only supports the name
option.
dir
The directory for storing your app's configuration file.
name
- Type:
string
- Default:
config
Configuration file name without extension.
ext
- Type:
string
- Default:
.json
Configuration file extension.
defaults
Default config used if there are no existing config.
serializer
Provides functionality to serialize object types to UTF-8 strings and to deserialize UTF-8 strings into object types.
By default, JSON.stringify
is used for serialization and JSON.parse
is used for deserialization.
You would usually not need this, but it could be useful if you want to use a format other than JSON.
Type Signature
interface Serializer<T> {
read: (raw: string) => T
write: (value: T) => string
}
schema
JSON Schema to validate your config data.
Under the hood, we use the ajv JSON Schema validator to validate config data.
You should define your schema as an object where each key is the name of your data's property and each value is a JSON schema used to validate that property.
import { Conf } from 'electron-conf/main'
const schema = {
type: 'object',
properties: {
foo: {
type: 'string',
maxLength: 10,
nullable: true
}
}
}
const conf = new Conf({ schema })
migrations
You can customize versions and perform operations to migrate configurations. When instantiated, it will be compared with the version number of the configuration file and a higher version migration operation will be performed.
Note: The migration version must be greater than 0
. A new version is defined on each migration and is incremented on the previous version.
import { Conf } from 'electron-conf/main'
const migrations = [
{
version: 1,
hook: (conf, version): void => {
conf.set('foo', 'a')
console.log(`migrate from ${version} to 1`)
}
},
{
version: 2,
hook: (conf, version): void => {
conf.set('foo', 'b')
console.log(`migrate from ${version} to 2`)
}
}
]
const conf = new Conf({ migrations })
Type Signature
type Migration<T extends Record<string, any>> = {
version: number
hook: (instance: BaseConf<T>, currentVersion: number) => void
}
Instance Methods
You can use dot-notation in a key to access nested properties.
The instance is iterable
so you can use it directly in a for…of
loop.
[!NOTE]
All methods in renderer are promise-based.
.get(key, defaultValue?)
Get an item or defaultValue if the item does not exist.
.set(key, value)
Set an item.
.set(object)
Set an item or multiple items at once.
conf.set({ foo: 1, a: 'b' })
.reset(...keys)
Reset items to their default values, as defined by the defaults or schema option.
.has(key)
Check if an item exists.
.delete(key)
Delete an item.
.clear()
Delete all items.
.onDidChange(key, callback)
callback
: (newValue, oldValue) => {}
Watches the given key
, calling callback
on any changes.
When a key is first set oldValue
will be undefined
, and when a key is deleted newValue
will be undefined
.
Returns a function which you can use to unsubscribe:
const unsubscribe = conf.onDidChange(key, callback)
unsubscribe()
[!TIP]
Not available in rendering process
.onDidAnyChange(callback)
callback
: (newValue, oldValue) => {}
Watches the whole config object, calling callback
on any changes.
oldValue
and newValue
will be the config object before and after the change, respectively. You must compare oldValue
to newValue
to find out what changed.
Returns a function which you can use to unsubscribe:
const unsubscribe = store.onDidAnyChange(callback)
unsubscribe()
[!TIP]
Not available in rendering process
.fileName
Get the configuration file path.
[!TIP]
Not available in rendering process
Credits
Conf, simple config handling for your app or module.