fix: replace ESM store with native json-store and package Windows desktop build

This commit is contained in:
djjdjdbf9 2026-10-24 23:59:19 +03:00
parent 2c0b0ffc89
commit d4eda5f36e
5 changed files with 86 additions and 27 deletions

View File

@ -115,7 +115,17 @@
---
## H. Instructions for the Next AI Agent
## H. Important Decisions
| Decision | Reason | Alternatives Rejected |
|---|---|---|
| Native JSON store (`JsonStore`) over `electron-store` | `electron-store` v10 is pure ESM causing `ERR_REQUIRE_ESM` in Electron CJS main bundle; native `fs` JSON store has 0 external dependencies and 100% synchronous stability | `electron-store` v10 (rejected: ESM runtime collision) |
| Atomic JSON store over `better-sqlite3` | Eliminates requirement for Visual Studio C++ compilers and node-gyp native compilation on target user PCs | `better-sqlite3` (rejected: requires C++ build tools) |
| electron-vite over vanilla Vite | Direct Electron HMR and optimized dual-bundle build pipeline | Custom webpack, Create React App |
---
## I. Instructions for the Next AI Agent
1. **Read `PROJECT_STATE.md` completely before making changes.**
2. **Read `DESIGN.md` before modifying any UI.** Adhere strictly to the Axiom design system.

View File

@ -1,4 +1,4 @@
import Store from 'electron-store'
import { JsonStore } from './json-store'
import { createLogger } from '../logger'
import type { Repository } from '../../shared/types/git.types'
@ -10,18 +10,14 @@ interface DatabaseSchema {
graphLayout: Record<string, { x: number; y: number }>
}
let store: Store<DatabaseSchema> | null = null
let store: JsonStore<DatabaseSchema> | null = null
export function getDb(): Store<DatabaseSchema> {
export function getDb(): JsonStore<DatabaseSchema> {
if (!store) {
store = new Store<DatabaseSchema>({
name: 'flowgit-data',
defaults: {
repositories: [],
uiState: {},
graphLayout: {},
},
clearInvalidConfig: true,
store = new JsonStore<DatabaseSchema>('flowgit-data', {
repositories: [],
uiState: {},
graphLayout: {},
})
}
return store
@ -47,7 +43,7 @@ export function getRepository(id: string): Repository | null {
export function upsertRepository(repo: Omit<Repository, 'remotes'>): void {
const db = getDb()
const repos = db.get('repositories') ?? []
const repos = [...(db.get('repositories') ?? [])]
const existingIndex = repos.findIndex(r => r.id === repo.id || r.path === repo.path)
const fullRepo: Repository = {
@ -78,7 +74,7 @@ export function removeRepository(id: string): void {
export function pinRepository(id: string, pinned: boolean): void {
const db = getDb()
const repos = db.get('repositories') ?? []
const repos = [...(db.get('repositories') ?? [])]
const repo = repos.find(r => r.id === id)
if (repo) {
repo.isPinned = pinned
@ -95,7 +91,7 @@ export function getUiState(key: string): string | null {
export function setUiState(key: string, value: string): void {
const db = getDb()
const state = db.get('uiState') ?? {}
const state = { ...(db.get('uiState') ?? {}) }
state[key] = value
db.set('uiState', state)
}

View File

@ -0,0 +1,52 @@
import { app } from 'electron'
import { join } from 'path'
import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'fs'
export class JsonStore<T extends object> {
private filePath: string
private data: T
constructor(name: string, defaults: T) {
let dir = ''
try {
dir = app.getPath('userData')
} catch {
dir = join(process.cwd(), '.flowgit-data')
}
mkdirSync(dir, { recursive: true })
this.filePath = join(dir, `${name}.json`)
if (existsSync(this.filePath)) {
try {
const raw = readFileSync(this.filePath, 'utf8')
this.data = { ...defaults, ...JSON.parse(raw) }
} catch {
this.data = { ...defaults }
}
} else {
this.data = { ...defaults }
this.save()
}
}
get<K extends keyof T>(key: K): T[K] {
return this.data[key]
}
set<K extends keyof T>(key: K, value: T[K]): void {
this.data[key] = value
this.save()
}
getAll(): T {
return { ...this.data }
}
private save(): void {
try {
writeFileSync(this.filePath, JSON.stringify(this.data, null, 2), 'utf8')
} catch (err) {
console.error(`Failed to write store to ${this.filePath}:`, err)
}
}
}

View File

@ -1,4 +1,4 @@
import Store from 'electron-store'
import { JsonStore } from '../persistence/json-store'
import type { AppSettings } from '../../shared/types/ipc.types'
const defaults: AppSettings = {
@ -14,20 +14,23 @@ const defaults: AppSettings = {
confirmDestructive: true,
}
const store = new Store<AppSettings>({
name: 'settings',
defaults,
clearInvalidConfig: true,
})
let store: JsonStore<AppSettings> | null = null
function getStore(): JsonStore<AppSettings> {
if (!store) {
store = new JsonStore<AppSettings>('settings', defaults)
}
return store
}
export function getSettings(): AppSettings {
return store.store
return getStore().getAll()
}
export function getSetting<K extends keyof AppSettings>(key: K): AppSettings[K] {
return store.get(key)
return getStore().get(key)
}
export function setSetting<K extends keyof AppSettings>(key: K, value: AppSettings[K]): void {
store.set(key, value)
getStore().set(key, value)
}

View File

@ -17,9 +17,7 @@
"dist": "npm run build && electron-builder",
"dist:dir": "npm run build && electron-builder --dir"
},
"dependencies": {
"electron-store": "^10.0.0"
},
"dependencies": {},
"devDependencies": {
"@electron-toolkit/preload": "^3.0.1",
"@electron-toolkit/utils": "^3.0.0",