Files
ESH-Media/src/main/database.ts
eshmeshek ecb5e7e49f init: media-center v2
Rewrite of ESH-Media v1 with separated main/renderer/shared architecture
(vite-plugin-electron, React 18, react-router-dom). Includes NeDB storage,
electron-store config, proxy manager with FoxyProxy/uBlock extensions,
custom server-checked updater, NSIS installer.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 23:49:43 +03:00

148 lines
3.6 KiB
TypeScript

import Datastore from 'nedb';
import * as path from 'path';
import { Bookmark, AppSettings } from '../shared/types';
import { DEFAULT_SETTINGS } from '../shared/constants';
import { v4 as uuidv4 } from 'uuid';
export class DatabaseManager {
private bookmarksDb: Datastore<any>;
private settingsDb: Datastore<any>;
constructor(userDataPath: string) {
this.bookmarksDb = new Datastore({
filename: path.join(userDataPath, 'bookmarks.db'),
autoload: false,
});
this.settingsDb = new Datastore({
filename: path.join(userDataPath, 'settings.db'),
autoload: false,
});
}
async init(): Promise<void> {
return new Promise((resolve, reject) => {
this.bookmarksDb.loadDatabase((err) => {
if (err) {
reject(err);
return;
}
this.settingsDb.loadDatabase((err) => {
if (err) {
reject(err);
return;
}
// Create indexes
this.bookmarksDb.ensureIndex({ fieldName: 'id', unique: true });
this.bookmarksDb.ensureIndex({ fieldName: 'siteId' });
console.log('Database initialized');
resolve();
});
});
});
}
// Bookmarks methods
async getBookmarks(): Promise<Bookmark[]> {
return new Promise((resolve, reject) => {
this.bookmarksDb
.find({})
.sort({ createdAt: -1 })
.exec((err, docs) => {
if (err) {
reject(err);
} else {
resolve(docs as Bookmark[]);
}
});
});
}
async addBookmark(bookmark: Omit<Bookmark, 'id' | 'createdAt'>): Promise<Bookmark> {
const newBookmark: Bookmark = {
...bookmark,
id: uuidv4(),
createdAt: new Date().toISOString(),
};
return new Promise((resolve, reject) => {
this.bookmarksDb.insert(newBookmark, (err, doc) => {
if (err) {
reject(err);
} else {
resolve(doc as Bookmark);
}
});
});
}
async removeBookmark(id: string): Promise<boolean> {
return new Promise((resolve, reject) => {
this.bookmarksDb.remove({ id }, {}, (err, numRemoved) => {
if (err) {
reject(err);
} else {
resolve(numRemoved > 0);
}
});
});
}
async getBookmarksBySite(siteId: string): Promise<Bookmark[]> {
return new Promise((resolve, reject) => {
this.bookmarksDb
.find({ siteId })
.sort({ createdAt: -1 })
.exec((err, docs) => {
if (err) {
reject(err);
} else {
resolve(docs as Bookmark[]);
}
});
});
}
// Settings methods
async getSettings(): Promise<AppSettings> {
return new Promise((resolve, reject) => {
this.settingsDb.findOne({ type: 'app-settings' }, (err, doc) => {
if (err) {
reject(err);
} else if (doc) {
resolve(doc as AppSettings);
} else {
// Return default settings if not found
resolve(DEFAULT_SETTINGS);
}
});
});
}
async saveSettings(settings: AppSettings): Promise<void> {
return new Promise((resolve, reject) => {
this.settingsDb.update(
{ type: 'app-settings' },
{ ...settings, type: 'app-settings' },
{ upsert: true },
(err) => {
if (err) {
reject(err);
} else {
resolve();
}
}
);
});
}
close(): void {
// NeDB doesn't require explicit closing, but we can compact databases
this.bookmarksDb.persistence.compactDatafile();
this.settingsDb.persistence.compactDatafile();
}
}