feat: Verdaccio 缓存可视化管理面板(前端 + 后端 + Docker)
- 前端 Vue3+Vite+Element Plus 按需引入,双主题(bright/dark)CSS 变量 - 三端响应式(桌面/平板/手机),登录/概览/检索/阈值/忽略/动态 6 页面 - 后端 Express + better-sqlite3,目录扫描 + demo 模式,清理原子写入 - Dockerfile 多阶段构建 + docker-compose(storage 只读挂载)
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
* SQLite 数据层(§4.1)
|
||||
* 表:settings / ignored_packages / logs
|
||||
*/
|
||||
import Database from 'better-sqlite3'
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
||||
// 数据目录:环境变量 DATA_DIR 可覆盖(Docker 挂载 manager-data)
|
||||
const DATA_DIR = process.env.DATA_DIR || path.join(__dirname, 'data')
|
||||
fs.mkdirSync(DATA_DIR, { recursive: true })
|
||||
|
||||
const db = new Database(path.join(DATA_DIR, 'manager.db'))
|
||||
db.pragma('journal_mode = WAL')
|
||||
|
||||
db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS settings (
|
||||
key TEXT PRIMARY KEY,
|
||||
value TEXT
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS ignored_packages (
|
||||
pkg_name TEXT PRIMARY KEY,
|
||||
ignored_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS logs (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
pkg_name TEXT,
|
||||
deleted_versions TEXT,
|
||||
deleted_count INTEGER,
|
||||
freed_space TEXT,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
`)
|
||||
|
||||
// —— settings ——
|
||||
export function getSetting(key, def = null) {
|
||||
const row = db.prepare('SELECT value FROM settings WHERE key = ?').get(key)
|
||||
return row ? row.value : def
|
||||
}
|
||||
|
||||
export function setSetting(key, value) {
|
||||
db.prepare(
|
||||
'INSERT INTO settings (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value',
|
||||
).run(key, String(value))
|
||||
}
|
||||
|
||||
// —— ignored ——
|
||||
export function getIgnored() {
|
||||
return db.prepare('SELECT pkg_name FROM ignored_packages ORDER BY ignored_at DESC').all().map(r => r.pkg_name)
|
||||
}
|
||||
|
||||
export function getIgnoredRows() {
|
||||
return db.prepare('SELECT pkg_name, ignored_at FROM ignored_packages ORDER BY ignored_at DESC').all()
|
||||
}
|
||||
|
||||
export function isIgnored(pkgName) {
|
||||
return !!db.prepare('SELECT 1 FROM ignored_packages WHERE pkg_name = ?').get(pkgName)
|
||||
}
|
||||
|
||||
export function addIgnored(pkgName) {
|
||||
db.prepare(
|
||||
'INSERT INTO ignored_packages (pkg_name) VALUES (?) ON CONFLICT(pkg_name) DO NOTHING',
|
||||
).run(pkgName)
|
||||
}
|
||||
|
||||
export function removeIgnored(pkgName) {
|
||||
db.prepare('DELETE FROM ignored_packages WHERE pkg_name = ?').run(pkgName)
|
||||
}
|
||||
|
||||
// —— logs ——
|
||||
export function addLog({ pkgName, deletedVersions, deletedCount, freedSpace }) {
|
||||
const info = db.prepare(
|
||||
'INSERT INTO logs (pkg_name, deleted_versions, deleted_count, freed_space) VALUES (?, ?, ?, ?)',
|
||||
).run(pkgName, deletedVersions, deletedCount, freedSpace)
|
||||
return info.lastInsertRowid
|
||||
}
|
||||
|
||||
export function getLogs(limit = 50) {
|
||||
return db.prepare(
|
||||
'SELECT * FROM logs ORDER BY id DESC LIMIT ?',
|
||||
).all(limit)
|
||||
}
|
||||
|
||||
export default db
|
||||
Reference in New Issue
Block a user