• Stars
    star
    8
  • Rank 2,099,232 (Top 42 %)
  • Language
    TypeScript
  • License
    MIT License
  • Created almost 2 years ago
  • Updated 2 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A minimalistic, secure, type-safe data store for Electron

Stand With Ukraine


Nano Electron store

Buy Me A Coffee

A minimalistic, secure, type-safe data store for Electron. This package is flat wrapper around fs-nano-store and with a few strict checks to allow safely use it in renderer.

Note See the full fs-nano-store documentation for more information about how store works

Installation

npm install electron-nano-store

or

pnpm add electron-nano-store

or

yarn add electron-nano-store

Usage

Simple

Just expose in main world defineStore function and use it directly in your renderer anywhere.

// In Electron Preload Script
import { defineStore } from "electron-nano-store"
import { contextBridge } from 'electron'

contextBridge.exposeInMainWorld('defineStore', defineStore)
// In Renderer
const store = await defineStore('user')

store.set('role', 'admin')
console.log(store.get('role')) // -> 'admin'

Recommended

As an additional safety precaution, you can choose not to expose a defineStore function, but instead expose an already defined store. The examples below also show an example of use with TypeScript.

// contracts.ts
export type UserStore = {
	role: 'admin' | 'user'
}
// in Preload Script
import { defineStore } from "electron-nano-store"
import { contextBridge } from 'electron'
import type { UserStore } from 'contracts.ts'

const userStorePromise = defineStore<UserStore>('user')
contextBridge.exposeInMainWorld('userStorePromise', userStorePromise)
// In Renderer
import type { UserStore } from 'contracts.ts'
import type { defineStore } from 'electron-nano-store'

declare global {
	interface Window {
		userStorePromise: ReturnType<typeof defineStore<UserStore>>
	}
}
const store = await window.userStorePromise
store.set('role', 'admin')
console.log(store.get('role')) // -> 'admin'

store.set('role', 'wrong-role') // TS Error: Argument of type '"wrong-role"' is not assignable to parameter of type '"admin" | "user"'

Recommended with automatic type inference

The exchange of types between the preload and the renderer can be a little annoying and complicated. So you can use unplugin-auto-expose for automatic type inference

// in Preload Script
import { defineStore } from "electron-nano-store"

type UserStore = {
	role: 'admin' | 'user'
}
export const userStorePromise = defineStore<UserStore>('user')
// In Renderer
import { userStorePromise } from '#preload'

const store = await userStorePromise

In Main

This package was intentionally designed with many restrictions for use in preload. If you want to use it in main, or you need more control you should use fs-nano-store directly

// In Main
import { defineStore } from 'fs-nano-store'
import { resolveStoreFilepath } from 'electron-nano-store'
import { app } from 'electron'

const store = await defineStore(
	resolveStoreFilepath(
		'store-name',
		app.getPath('userData')
	)
)

Listen store changes in Renderer

fs-nano-store automatically tracks all changes to the store, and emit a changed event if the store has been changed out of context.

However, electron does not allow you to expose EventEmitter to the main world. This means that even though it defines and returns change property, you can't add listeners directly.

const { changes } = defineStore('store-name')
changes.addListener // undefined

To do this, you must define store in the preload context, add listeners there, and proxy all events to an existing EventTarget, such as a window

// in Preload Script
const storePromise = defineStore<Store>('user')
storePromise.then(({ changes }) => {
	changes.addListener(
		'changed',
		() => globalThis.dispatchEvent(new CustomEvent('user:changed')),
	)
})
// in Renderer
globalThis.addEventListener(
	'user:changed',
	() => { /* ... */
	}
)

Security limitation

  1. You can't somehow change where are storage files placed in filesystems. It always in electron.app.getPath('userData') directory defined by electron. Since the defineStore function may be exposed to a non-secure context, this is done to prevent malicious code from making uncontrolled writes anywhere on the file system.
    // 🚫 Harmful use
    defineStore('.privat-config', { customPath: '/somewhere/in/user/filesystem/' })

    Note If you need create store in some different location, you should make your own wrapper around fs-nano-store. Look how use In Main.

  2. For the same reasons, you cannot use any path fragments in the repository name
    // 🚫 Harmful use
    defineStore('../../somewhere/in/user/filesystem/privat-config')

More Repositories

1

vite-electron-builder

Secure boilerplate for Electron app based on Vite. TypeScript + Vue/React/Angular/Svelte/Vanilla
TypeScript
2,332
star
2

iconify-prerendered

A superset standalone icon-components for Vue with zero dependencies. Designed for ease of use and high performance.
TypeScript
84
star
3

unplugin-auto-expose

Plugins for automatic exposeInMainWorld everything you exported from preload and easily importing exposed api in renderer
TypeScript
39
star
4

play-shikimori-online

Расширение позволяет смотреть аниме онлайн и автоматическии синхронизировать его с вашим списком на Шикимори (shikimori.org и shikimori.one)
JavaScript
33
star
5

anime-library

Бесплатное Приложение для просмотра аниме онлайн
TypeScript
29
star
6

youtube-forward-timeline

Browser extension for fast-forward YouTube video to the next section.
JavaScript
18
star
7

Vk-Emoji

Replace symbols emoticons VK the corresponding HTML code
JavaScript
12
star
8

dts-for-context-bridge

Generate `.d.ts` file for Electron `contextBridge.exposeInMainWorld` calls
JavaScript
9
star
9

fs-nano-store

A minimalistic, secure, type-safe, zero-dependencies, persistent data store
TypeScript
3
star
10

vite-plugin-vue-chrome-i18n

A plugin for the Vite that extracts and scope translations from Vue Single File Component and combines them into a localization file for browser extensions.
TypeScript
2
star
11

admitad-data-studio-connector

Google Data Studio Connector for Admitad advertiser reports
TypeScript
2
star
12

anime-news-crawler-bot

Чат бот, который ищет аниме новости по выбранным франшизам
JavaScript
2
star
13

kozack.me

⁨⁨⁨Alex⁩ ⁨Kozack⁩⁩ — ⁨Full stack web developer⁩⁩ — ⁨Personal site⁩
TypeScript
1
star
14

HWL-uk-pak-debugger

TypeScript
1
star
15

HYWenHei-Extended-Font

HYWenHei (Genshin Impact) Font extendet to support additional languages
1
star
16

rollup-plugin-dynamic-macros

A minimalist Rollup and Vite plugin for creating compile-time macros.
JavaScript
1
star
17

anime-tracker-bot

TypeScript
1
star
18

shikimori-to-anitube

Скрипт для tampermonkey, що додає прямі посилання з shikimori.one на anitube.in.ua
JavaScript
1
star
19

comebackalive-paywall

Генератор посилань на захищений контент. Захищений контент буде доступний користувачу лише після пожертви у фонд Повернись Живим
Vue
1
star
20

public-accesebility-reports

1
star