update
This commit is contained in:
@@ -1,12 +1,7 @@
|
||||
// packages/backend/src/repositories/terminal-theme.repository.ts
|
||||
import { Database } from 'sqlite3'; // Import Database type if needed for type hints
|
||||
import { getDbInstance, runDb, getDb, allDb } from '../database/connection'; // Import new async helpers, including getDb
|
||||
// Remove the incorrect import of DbTerminalThemeRow
|
||||
import { Database } from 'sqlite3';
|
||||
import { getDbInstance, runDb, getDb, allDb } from '../database/connection';
|
||||
import { TerminalTheme, CreateTerminalThemeDto, UpdateTerminalThemeDto } from '../types/terminal-theme.types';
|
||||
import { defaultXtermTheme } from '../config/default-themes';
|
||||
|
||||
// Define the interface for the raw database row structure
|
||||
// Interface matching the schema in schema.ts
|
||||
interface DbTerminalThemeRow {
|
||||
id: number;
|
||||
name: string;
|
||||
@@ -36,23 +31,18 @@ interface DbTerminalThemeRow {
|
||||
updated_at: number;
|
||||
}
|
||||
|
||||
// SQL_CREATE_TABLE and createTableIfNotExists removed as initialization is handled in database/connection.ts
|
||||
|
||||
// 辅助函数:将数据库行转换为 TerminalTheme 对象
|
||||
// Add type annotation for the input row
|
||||
const mapRowToTerminalTheme = (row: DbTerminalThemeRow): TerminalTheme => {
|
||||
// Basic check if row exists and has id property
|
||||
if (!row || typeof row.id === 'undefined') {
|
||||
console.error("mapRowToTerminalTheme received invalid row:", row);
|
||||
// Return a default or throw an error, depending on desired behavior
|
||||
// For now, let's throw an error to make the issue visible
|
||||
throw new Error("Invalid database row provided to mapRowToTerminalTheme");
|
||||
}
|
||||
try {
|
||||
return {
|
||||
_id: row.id.toString(),
|
||||
name: row.name,
|
||||
// Reconstruct themeData from individual columns
|
||||
themeData: {
|
||||
foreground: row.foreground ?? undefined,
|
||||
background: row.background ?? undefined,
|
||||
@@ -77,16 +67,12 @@ const mapRowToTerminalTheme = (row: DbTerminalThemeRow): TerminalTheme => {
|
||||
brightWhite: row.bright_white ?? undefined,
|
||||
},
|
||||
isPreset: row.theme_type === 'preset',
|
||||
// isSystemDefault needs to be handled differently, maybe based on name 'default'?
|
||||
// For now, let's assume it's not directly mapped or needed here.
|
||||
isSystemDefault: row.name === 'default', // Tentative mapping based on name
|
||||
isSystemDefault: row.name === 'default',
|
||||
createdAt: row.created_at,
|
||||
updatedAt: row.updated_at,
|
||||
};
|
||||
} catch (e: any) {
|
||||
// Log the entire row for debugging instead of the non-existent theme_data
|
||||
console.error(`Error mapping theme data for theme ID ${row.id}:`, e.message, "Raw row:", row);
|
||||
// Return a partially mapped object or throw error
|
||||
throw new Error(`Failed to map theme data for theme ID ${row.id}`);
|
||||
}
|
||||
};
|
||||
@@ -98,23 +84,20 @@ const mapRowToTerminalTheme = (row: DbTerminalThemeRow): TerminalTheme => {
|
||||
export const findAllThemes = async (): Promise<TerminalTheme[]> => {
|
||||
try {
|
||||
const db = await getDbInstance();
|
||||
// Specify the expected row type for allDb
|
||||
// Correct the ORDER BY clause to use theme_type and sort presets first
|
||||
const rows = await allDb<DbTerminalThemeRow>(db, 'SELECT * FROM terminal_themes ORDER BY CASE theme_type WHEN \'preset\' THEN 0 ELSE 1 END ASC, name ASC');
|
||||
// Filter out potential errors during mapping
|
||||
return rows.map(row => {
|
||||
try {
|
||||
return mapRowToTerminalTheme(row);
|
||||
} catch (mapError: any) {
|
||||
console.error(`Error mapping row ID ${row?.id}:`, mapError.message);
|
||||
return null; // Or handle differently
|
||||
return null;
|
||||
}
|
||||
}).filter((theme): theme is TerminalTheme => theme !== null);
|
||||
} catch (err: any) { // Add type annotation for err
|
||||
} catch (err: any) {
|
||||
console.error('查询所有终端主题失败:', err.message);
|
||||
// 添加详细错误日志
|
||||
console.error('详细错误:', err);
|
||||
throw new Error('查询终端主题失败'); // Re-throw or handle error appropriately
|
||||
throw new Error('查询终端主题失败');
|
||||
}
|
||||
};
|
||||
|
||||
@@ -126,15 +109,13 @@ export const findAllThemes = async (): Promise<TerminalTheme[]> => {
|
||||
export const findThemeById = async (id: number): Promise<TerminalTheme | null> => {
|
||||
if (isNaN(id) || id <= 0) {
|
||||
console.error("findThemeById called with invalid ID:", id);
|
||||
return null; // Return null for invalid IDs
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
const db = await getDbInstance();
|
||||
// Specify the expected row type for getDbRow
|
||||
// Use getDb instead of the non-existent getDbRow
|
||||
const row = await getDb<DbTerminalThemeRow>(db, 'SELECT * FROM terminal_themes WHERE id = ?', [id]);
|
||||
return row ? mapRowToTerminalTheme(row) : null;
|
||||
} catch (err: any) { // Add type annotation for err
|
||||
} catch (err: any) {
|
||||
console.error(`查询 ID 为 ${id} 的终端主题失败:`, err.message);
|
||||
throw new Error('查询终端主题失败');
|
||||
}
|
||||
@@ -146,10 +127,10 @@ export const findThemeById = async (id: number): Promise<TerminalTheme | null> =
|
||||
* @returns Promise<TerminalTheme> 新创建的主题
|
||||
*/
|
||||
export const createTheme = async (themeDto: CreateTerminalThemeDto): Promise<TerminalTheme> => {
|
||||
const nowSeconds = Math.floor(Date.now() / 1000); // Use seconds for DB consistency
|
||||
const nowSeconds = Math.floor(Date.now() / 1000);
|
||||
const theme = themeDto.themeData;
|
||||
|
||||
// Define columns based on the DbTerminalThemeRow interface (excluding id, created_at, updated_at)
|
||||
|
||||
const columns = [
|
||||
'name', 'theme_type', 'foreground', 'background', 'cursor', 'cursor_accent',
|
||||
'selection_background', 'black', 'red', 'green', 'yellow', 'blue',
|
||||
@@ -157,14 +138,13 @@ export const createTheme = async (themeDto: CreateTerminalThemeDto): Promise<Ter
|
||||
'bright_yellow', 'bright_blue', 'bright_magenta', 'bright_cyan', 'bright_white',
|
||||
'created_at', 'updated_at'
|
||||
];
|
||||
// Map themeDto data to corresponding columns, using null for missing optional values
|
||||
const values = [
|
||||
themeDto.name, 'user', // theme_type is 'user' for created themes
|
||||
themeDto.name, 'user',
|
||||
theme?.foreground ?? null, theme?.background ?? null, theme?.cursor ?? null, theme?.cursorAccent ?? null,
|
||||
theme?.selectionBackground ?? null, theme?.black ?? null, theme?.red ?? null, theme?.green ?? null, theme?.yellow ?? null, theme?.blue ?? null,
|
||||
theme?.magenta ?? null, theme?.cyan ?? null, theme?.white ?? null, theme?.brightBlack ?? null, theme?.brightRed ?? null, theme?.brightGreen ?? null,
|
||||
theme?.brightYellow ?? null, theme?.brightBlue ?? null, theme?.brightMagenta ?? null, theme?.brightCyan ?? null, theme?.brightWhite ?? null,
|
||||
nowSeconds, nowSeconds // Use seconds for timestamps
|
||||
nowSeconds, nowSeconds
|
||||
];
|
||||
const placeholders = columns.map(() => '?').join(', ');
|
||||
|
||||
@@ -175,8 +155,7 @@ export const createTheme = async (themeDto: CreateTerminalThemeDto): Promise<Ter
|
||||
|
||||
try {
|
||||
const db = await getDbInstance();
|
||||
const result = await runDb(db, sql, values); // Use the mapped values array
|
||||
// Ensure lastID is valid before trying to find the theme
|
||||
const result = await runDb(db, sql, values);
|
||||
if (typeof result.lastID !== 'number' || result.lastID <= 0) {
|
||||
throw new Error('创建主题后未能获取有效的 lastID');
|
||||
}
|
||||
@@ -184,10 +163,9 @@ export const createTheme = async (themeDto: CreateTerminalThemeDto): Promise<Ter
|
||||
if (newTheme) {
|
||||
return newTheme;
|
||||
} else {
|
||||
// This case might happen if findThemeById fails for some reason
|
||||
throw new Error(`创建主题后未能检索到 ID 为 ${result.lastID} 的主题`);
|
||||
}
|
||||
} catch (err: any) { // Add type annotation for err
|
||||
} catch (err: any) {
|
||||
console.error('创建新终端主题失败:', err.message);
|
||||
if (err.message.includes('UNIQUE constraint failed')) {
|
||||
throw new Error(`主题名称 "${themeDto.name}" 已存在。`);
|
||||
@@ -215,7 +193,7 @@ export const updateTheme = async (id: number, themeDto: UpdateTerminalThemeDto):
|
||||
const db = await getDbInstance();
|
||||
const result = await runDb(db, sql, [themeDto.name, themeDataJson, now, id]);
|
||||
return result.changes > 0;
|
||||
} catch (err: any) { // Add type annotation for err
|
||||
} catch (err: any) {
|
||||
console.error(`更新 ID 为 ${id} 的终端主题失败:`, err.message);
|
||||
if (err.message.includes('UNIQUE constraint failed')) {
|
||||
throw new Error(`主题名称 "${themeDto.name}" 已存在。`);
|
||||
@@ -231,13 +209,12 @@ export const updateTheme = async (id: number, themeDto: UpdateTerminalThemeDto):
|
||||
* @returns Promise<boolean> 是否成功删除
|
||||
*/
|
||||
export const deleteTheme = async (id: number): Promise<boolean> => {
|
||||
// Correct the WHERE clause to use theme_type = 'user' instead of is_preset = 0
|
||||
const sql = 'DELETE FROM terminal_themes WHERE id = ? AND theme_type = \'user\'';
|
||||
try {
|
||||
const db = await getDbInstance();
|
||||
const result = await runDb(db, sql, [id]);
|
||||
return result.changes > 0;
|
||||
} catch (err: any) { // Add type annotation for err
|
||||
} catch (err: any) {
|
||||
console.error(`删除 ID 为 ${id} 的终端主题失败:`, err.message);
|
||||
throw new Error('删除终端主题失败');
|
||||
}
|
||||
@@ -252,20 +229,15 @@ export const initializePresetThemes = async (db: Database, presets: Array<Omit<T
|
||||
console.log('[DB Init] 开始检查并初始化预设主题...');
|
||||
// 在这里添加日志,显示总共要处理多少个预设主题
|
||||
console.log(`[DB Init] 发现 ${presets.length} 个预设主题定义。`);
|
||||
const nowSeconds = Math.floor(Date.now() / 1000); // Use seconds for DB consistency
|
||||
// const db = await getDbInstance(); // Use the passed db instance
|
||||
const nowSeconds = Math.floor(Date.now() / 1000);
|
||||
|
||||
for (const preset of presets) {
|
||||
// 在循环开始时添加日志,显示正在处理哪个主题
|
||||
console.log(`[DB Init] 正在处理预设主题: "${preset.name}"`);
|
||||
try {
|
||||
// Check using name and theme_type
|
||||
const existing = await getDb<{ id: number }>(db, `SELECT id FROM terminal_themes WHERE name = ? AND theme_type = 'preset'`, [preset.name]);
|
||||
|
||||
if (!existing) {
|
||||
// 添加日志,表明正在插入新主题
|
||||
console.log(`[DB Init] 主题 "${preset.name}" 不存在,正在插入...`);
|
||||
// Map preset.themeData to individual columns
|
||||
const theme = preset.themeData;
|
||||
const columns = [
|
||||
'name', 'theme_type', 'foreground', 'background', 'cursor', 'cursor_accent',
|
||||
@@ -290,14 +262,10 @@ export const initializePresetThemes = async (db: Database, presets: Array<Omit<T
|
||||
await runDb(db, insertSql, values);
|
||||
console.log(`[DB Init] 预设主题 "${preset.name}" 已初始化到数据库。`);
|
||||
} else {
|
||||
// 取消注释并添加日志,表明主题已存在
|
||||
console.log(`[DB Init] 预设主题 "${preset.name}" 已存在,跳过初始化。`);
|
||||
}
|
||||
} catch (err: any) { // Add type annotation for err
|
||||
// Remove reference to non-existent preset_key
|
||||
} catch (err: any) {
|
||||
console.error(`[DB Init] 处理预设主题 "${preset.name}" 时出错:`, err.message);
|
||||
// Decide if one error should stop the whole process or just log and continue
|
||||
// throw err; // Uncomment to stop on first error
|
||||
}
|
||||
}
|
||||
console.log('[DB Init] 预设主题检查和初始化完成。');
|
||||
|
||||
Reference in New Issue
Block a user