mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-10 02:24:35 +08:00
feat: 添加更好的 SQLite3 模块加载和错误处理,更新相关组件以支持项目路径
This commit is contained in:
@@ -2,11 +2,11 @@
|
||||
* MCP Templates Database Module
|
||||
* Stores MCP server configurations as reusable templates
|
||||
*/
|
||||
import Database from 'better-sqlite3';
|
||||
import { existsSync, mkdirSync } from 'fs';
|
||||
import { join, dirname } from 'path';
|
||||
import { homedir } from 'os';
|
||||
import { StoragePaths, ensureStorageDir } from '../../config/storage-paths.js';
|
||||
import { createDatabase } from '../../utils/db-loader.js';
|
||||
|
||||
// Database path - uses centralized storage
|
||||
const DB_DIR = StoragePaths.global.databases();
|
||||
@@ -16,14 +16,15 @@ const DB_PATH = StoragePaths.global.mcpTemplates();
|
||||
ensureStorageDir(DB_DIR);
|
||||
|
||||
// Initialize database connection
|
||||
let db: Database.Database | null = null;
|
||||
let db: any | null = null;
|
||||
|
||||
/**
|
||||
* Get or create database connection
|
||||
*/
|
||||
function getDb(): Database.Database {
|
||||
function getDb(): any {
|
||||
if (!db) {
|
||||
db = new Database(DB_PATH);
|
||||
db = createDatabase(DB_PATH);
|
||||
if (!db) return null;
|
||||
initDatabase();
|
||||
}
|
||||
return db;
|
||||
@@ -33,7 +34,7 @@ function getDb(): Database.Database {
|
||||
* Initialize database schema
|
||||
*/
|
||||
function initDatabase() {
|
||||
const db = getDb();
|
||||
if (!db) return;
|
||||
|
||||
// Create templates table
|
||||
db.exec(`
|
||||
@@ -83,6 +84,7 @@ export interface McpTemplate {
|
||||
export function saveTemplate(template: McpTemplate): { success: boolean; id?: number; error?: string } {
|
||||
try {
|
||||
const db = getDb();
|
||||
if (!db) return { success: false, error: 'Database unavailable (native module issue)' };
|
||||
const now = Date.now();
|
||||
|
||||
const stmt = db.prepare(`
|
||||
@@ -125,6 +127,7 @@ export function saveTemplate(template: McpTemplate): { success: boolean; id?: nu
|
||||
export function getAllTemplates(): McpTemplate[] {
|
||||
try {
|
||||
const db = getDb();
|
||||
if (!db) return [];
|
||||
const rows = db.prepare('SELECT * FROM mcp_templates ORDER BY name').all();
|
||||
|
||||
return rows.map((row: any) => ({
|
||||
@@ -149,6 +152,7 @@ export function getAllTemplates(): McpTemplate[] {
|
||||
export function getTemplateByName(name: string): McpTemplate | null {
|
||||
try {
|
||||
const db = getDb();
|
||||
if (!db) return null;
|
||||
const row = db.prepare('SELECT * FROM mcp_templates WHERE name = ?').get(name);
|
||||
|
||||
if (!row) return null;
|
||||
@@ -175,6 +179,7 @@ export function getTemplateByName(name: string): McpTemplate | null {
|
||||
export function getTemplatesByCategory(category: string): McpTemplate[] {
|
||||
try {
|
||||
const db = getDb();
|
||||
if (!db) return [];
|
||||
const rows = db.prepare('SELECT * FROM mcp_templates WHERE category = ? ORDER BY name').all(category);
|
||||
|
||||
return rows.map((row: any) => ({
|
||||
@@ -199,6 +204,7 @@ export function getTemplatesByCategory(category: string): McpTemplate[] {
|
||||
export function deleteTemplate(name: string): { success: boolean; error?: string } {
|
||||
try {
|
||||
const db = getDb();
|
||||
if (!db) return { success: false, error: 'Database unavailable (native module issue)' };
|
||||
const result = db.prepare('DELETE FROM mcp_templates WHERE name = ?').run(name);
|
||||
|
||||
return {
|
||||
@@ -219,6 +225,7 @@ export function deleteTemplate(name: string): { success: boolean; error?: string
|
||||
export function searchTemplates(keyword: string): McpTemplate[] {
|
||||
try {
|
||||
const db = getDb();
|
||||
if (!db) return [];
|
||||
const searchPattern = `%${keyword}%`;
|
||||
const rows = db.prepare(`
|
||||
SELECT * FROM mcp_templates
|
||||
@@ -248,6 +255,7 @@ export function searchTemplates(keyword: string): McpTemplate[] {
|
||||
export function getAllCategories(): string[] {
|
||||
try {
|
||||
const db = getDb();
|
||||
if (!db) return [];
|
||||
const rows = db.prepare('SELECT DISTINCT category FROM mcp_templates WHERE category IS NOT NULL ORDER BY category').all();
|
||||
return rows.map((row: any) => row.category);
|
||||
} catch (error: unknown) {
|
||||
|
||||
@@ -1734,7 +1734,7 @@ async function toggleChineseResponse(enabled, target) {
|
||||
}
|
||||
|
||||
try {
|
||||
var response = await fetch('/api/language/chinese-response', {
|
||||
var response = await csrfFetch('/api/language/chinese-response', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ enabled: enabled, target: target })
|
||||
@@ -1799,7 +1799,7 @@ async function toggleWindowsPlatform(enabled) {
|
||||
windowsPlatformLoading = true;
|
||||
|
||||
try {
|
||||
var response = await fetch('/api/language/windows-platform', {
|
||||
var response = await csrfFetch('/api/language/windows-platform', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ enabled: enabled })
|
||||
@@ -1848,7 +1848,7 @@ async function toggleCodexCliEnhancement(enabled) {
|
||||
codexCliEnhancementLoading = true;
|
||||
|
||||
try {
|
||||
var response = await fetch('/api/language/codex-cli-enhancement', {
|
||||
var response = await csrfFetch('/api/language/codex-cli-enhancement', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ enabled: enabled, action: 'toggle' })
|
||||
@@ -1888,7 +1888,7 @@ async function refreshCodexCliEnhancement() {
|
||||
codexCliEnhancementLoading = true;
|
||||
|
||||
try {
|
||||
var response = await fetch('/api/language/codex-cli-enhancement', {
|
||||
var response = await csrfFetch('/api/language/codex-cli-enhancement', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ action: 'refresh' })
|
||||
|
||||
54
ccw/src/utils/db-loader.ts
Normal file
54
ccw/src/utils/db-loader.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* Database Loader - Centralized better-sqlite3 loading with native module error handling
|
||||
* Catches NODE_MODULE_VERSION mismatch errors and provides actionable fix instructions
|
||||
*/
|
||||
|
||||
let warningShown = false;
|
||||
|
||||
function showNativeModuleWarning(error: Error): void {
|
||||
if (warningShown) return;
|
||||
warningShown = true;
|
||||
|
||||
const isVersionMismatch = error.message?.includes('NODE_MODULE_VERSION') ||
|
||||
(error as any).code === 'ERR_DLOPEN_FAILED';
|
||||
|
||||
if (isVersionMismatch) {
|
||||
console.error(
|
||||
'\n[CCW] better-sqlite3 native module version mismatch.\n' +
|
||||
' The module was compiled for a different Node.js version.\n' +
|
||||
' Fix: run one of the following commands:\n' +
|
||||
' npm rebuild better-sqlite3\n' +
|
||||
' npm install better-sqlite3 --build-from-source\n'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load better-sqlite3 Database constructor with error handling.
|
||||
* Returns the Database class or null if loading fails.
|
||||
*/
|
||||
export function loadDatabase(): typeof import('better-sqlite3') | null {
|
||||
try {
|
||||
// Use dynamic import via require for native module
|
||||
const Database = require('better-sqlite3');
|
||||
return Database;
|
||||
} catch (error: any) {
|
||||
showNativeModuleWarning(error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a database instance with error handling.
|
||||
* Returns the database instance or null if creation fails.
|
||||
*/
|
||||
export function createDatabase(dbPath: string, options?: any): any | null {
|
||||
const Database = loadDatabase();
|
||||
if (!Database) return null;
|
||||
try {
|
||||
return new Database(dbPath, options);
|
||||
} catch (error: any) {
|
||||
showNativeModuleWarning(error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user