Spaces:
Sleeping
Sleeping
| ; | |
| var __importDefault = (this && this.__importDefault) || function (mod) { | |
| return (mod && mod.__esModule) ? mod : { "default": mod }; | |
| }; | |
| Object.defineProperty(exports, "__esModule", { value: true }); | |
| exports.database = void 0; | |
| exports.initializeDatabase = initializeDatabase; | |
| const sqlite3_1 = __importDefault(require("sqlite3")); | |
| const path_1 = __importDefault(require("path")); | |
| const fs_1 = __importDefault(require("fs")); | |
| // Enable verbose mode for debugging | |
| const Database = sqlite3_1.default.verbose().Database; | |
| class DatabaseConnection { | |
| constructor() { | |
| this.db = null; | |
| } | |
| async connect() { | |
| if (this.db) { | |
| return this.db; | |
| } | |
| const dbPath = process.env.DATABASE_URL || path_1.default.join(__dirname, '../../database.sqlite'); | |
| // Ensure directory exists | |
| const dbDir = path_1.default.dirname(dbPath); | |
| if (!fs_1.default.existsSync(dbDir)) { | |
| fs_1.default.mkdirSync(dbDir, { recursive: true }); | |
| } | |
| return new Promise((resolve, reject) => { | |
| this.db = new Database(dbPath, (err) => { | |
| if (err) { | |
| console.error('Error opening database:', err.message); | |
| reject(err); | |
| } | |
| else { | |
| console.log('Connected to SQLite database'); | |
| resolve(this.db); | |
| } | |
| }); | |
| }); | |
| } | |
| async query(sql, params = []) { | |
| const db = await this.connect(); | |
| return new Promise((resolve, reject) => { | |
| db.all(sql, params, (err, rows) => { | |
| if (err) | |
| reject(err); | |
| else | |
| resolve(rows || []); | |
| }); | |
| }); | |
| } | |
| async run(sql, params = []) { | |
| const db = await this.connect(); | |
| return new Promise((resolve, reject) => { | |
| db.run(sql, params, function (err) { | |
| if (err) { | |
| reject(err); | |
| } | |
| else { | |
| resolve({ | |
| lastID: this.lastID || 0, | |
| changes: this.changes || 0 | |
| }); | |
| } | |
| }); | |
| }); | |
| } | |
| async get(sql, params = []) { | |
| const db = await this.connect(); | |
| return new Promise((resolve, reject) => { | |
| db.get(sql, params, (err, row) => { | |
| if (err) | |
| reject(err); | |
| else | |
| resolve(row); | |
| }); | |
| }); | |
| } | |
| async close() { | |
| if (this.db) { | |
| return new Promise((resolve, reject) => { | |
| this.db.close((err) => { | |
| if (err) { | |
| reject(err); | |
| } | |
| else { | |
| this.db = null; | |
| resolve(); | |
| } | |
| }); | |
| }); | |
| } | |
| } | |
| } | |
| // Singleton instance | |
| exports.database = new DatabaseConnection(); | |
| // Database initialization function | |
| async function initializeDatabase() { | |
| const createTables = [ | |
| // Users table | |
| `CREATE TABLE IF NOT EXISTS users ( | |
| id INTEGER PRIMARY KEY AUTOINCREMENT, | |
| email TEXT UNIQUE NOT NULL, | |
| name TEXT NOT NULL, | |
| password_hash TEXT, | |
| avatar TEXT, | |
| google_id TEXT UNIQUE, | |
| email_verified BOOLEAN DEFAULT FALSE, | |
| verification_token TEXT, | |
| created_at DATETIME DEFAULT CURRENT_TIMESTAMP, | |
| updated_at DATETIME DEFAULT CURRENT_TIMESTAMP | |
| )`, | |
| // Tenants table | |
| `CREATE TABLE IF NOT EXISTS tenants ( | |
| id INTEGER PRIMARY KEY AUTOINCREMENT, | |
| name TEXT NOT NULL, | |
| subdomain TEXT UNIQUE, | |
| plan TEXT DEFAULT 'starter', | |
| settings TEXT DEFAULT '{}', | |
| created_at DATETIME DEFAULT CURRENT_TIMESTAMP, | |
| updated_at DATETIME DEFAULT CURRENT_TIMESTAMP | |
| )`, | |
| // User-Tenant relationships | |
| `CREATE TABLE IF NOT EXISTS user_tenants ( | |
| id INTEGER PRIMARY KEY AUTOINCREMENT, | |
| user_id INTEGER NOT NULL, | |
| tenant_id INTEGER NOT NULL, | |
| role TEXT DEFAULT 'owner', | |
| permissions TEXT DEFAULT '{}', | |
| created_at DATETIME DEFAULT CURRENT_TIMESTAMP, | |
| FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE, | |
| FOREIGN KEY (tenant_id) REFERENCES tenants (id) ON DELETE CASCADE, | |
| UNIQUE(user_id, tenant_id) | |
| )`, | |
| // Domains table | |
| `CREATE TABLE IF NOT EXISTS domains ( | |
| id INTEGER PRIMARY KEY AUTOINCREMENT, | |
| tenant_id INTEGER NOT NULL, | |
| domain TEXT NOT NULL, | |
| verified BOOLEAN DEFAULT FALSE, | |
| verification_token TEXT, | |
| created_at DATETIME DEFAULT CURRENT_TIMESTAMP, | |
| FOREIGN KEY (tenant_id) REFERENCES tenants (id) ON DELETE CASCADE | |
| )`, | |
| // Knowledge base table | |
| `CREATE TABLE IF NOT EXISTS knowledge_base ( | |
| id INTEGER PRIMARY KEY AUTOINCREMENT, | |
| tenant_id INTEGER NOT NULL, | |
| name TEXT NOT NULL, | |
| type TEXT NOT NULL, | |
| source TEXT NOT NULL, | |
| status TEXT DEFAULT 'processing', | |
| size INTEGER, | |
| metadata TEXT DEFAULT '{}', | |
| created_at DATETIME DEFAULT CURRENT_TIMESTAMP, | |
| updated_at DATETIME DEFAULT CURRENT_TIMESTAMP, | |
| FOREIGN KEY (tenant_id) REFERENCES tenants (id) ON DELETE CASCADE | |
| )`, | |
| // Chat sessions table | |
| `CREATE TABLE IF NOT EXISTS chat_sessions ( | |
| id INTEGER PRIMARY KEY AUTOINCREMENT, | |
| tenant_id INTEGER NOT NULL, | |
| domain TEXT, | |
| user_ip TEXT, | |
| user_agent TEXT, | |
| session_token TEXT UNIQUE NOT NULL, | |
| started_at DATETIME DEFAULT CURRENT_TIMESTAMP, | |
| ended_at DATETIME, | |
| resolved BOOLEAN DEFAULT FALSE, | |
| rating INTEGER, | |
| feedback TEXT, | |
| FOREIGN KEY (tenant_id) REFERENCES tenants (id) ON DELETE CASCADE | |
| )`, | |
| // Chat messages table | |
| `CREATE TABLE IF NOT EXISTS chat_messages ( | |
| id INTEGER PRIMARY KEY AUTOINCREMENT, | |
| session_id INTEGER NOT NULL, | |
| sender TEXT NOT NULL, -- 'user' or 'ai' | |
| message TEXT NOT NULL, | |
| metadata TEXT DEFAULT '{}', | |
| timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, | |
| FOREIGN KEY (session_id) REFERENCES chat_sessions (id) ON DELETE CASCADE | |
| )`, | |
| // Analytics events table | |
| `CREATE TABLE IF NOT EXISTS analytics_events ( | |
| id INTEGER PRIMARY KEY AUTOINCREMENT, | |
| tenant_id INTEGER NOT NULL, | |
| event_type TEXT NOT NULL, | |
| event_data TEXT DEFAULT '{}', | |
| timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, | |
| FOREIGN KEY (tenant_id) REFERENCES tenants (id) ON DELETE CASCADE | |
| )`, | |
| // Widget configurations table | |
| `CREATE TABLE IF NOT EXISTS widget_configs ( | |
| id INTEGER PRIMARY KEY AUTOINCREMENT, | |
| tenant_id INTEGER NOT NULL, | |
| config TEXT NOT NULL DEFAULT '{}', | |
| created_at DATETIME DEFAULT CURRENT_TIMESTAMP, | |
| updated_at DATETIME DEFAULT CURRENT_TIMESTAMP, | |
| FOREIGN KEY (tenant_id) REFERENCES tenants (id) ON DELETE CASCADE | |
| )` | |
| ]; | |
| const createIndexes = [ | |
| `CREATE INDEX IF NOT EXISTS idx_users_email ON users(email)`, | |
| `CREATE INDEX IF NOT EXISTS idx_users_google_id ON users(google_id)`, | |
| `CREATE INDEX IF NOT EXISTS idx_tenants_subdomain ON tenants(subdomain)`, | |
| `CREATE INDEX IF NOT EXISTS idx_user_tenants_user_id ON user_tenants(user_id)`, | |
| `CREATE INDEX IF NOT EXISTS idx_user_tenants_tenant_id ON user_tenants(tenant_id)`, | |
| `CREATE INDEX IF NOT EXISTS idx_domains_tenant_id ON domains(tenant_id)`, | |
| `CREATE INDEX IF NOT EXISTS idx_knowledge_base_tenant_id ON knowledge_base(tenant_id)`, | |
| `CREATE INDEX IF NOT EXISTS idx_chat_sessions_tenant_id ON chat_sessions(tenant_id)`, | |
| `CREATE INDEX IF NOT EXISTS idx_chat_sessions_token ON chat_sessions(session_token)`, | |
| `CREATE INDEX IF NOT EXISTS idx_chat_messages_session_id ON chat_messages(session_id)`, | |
| `CREATE INDEX IF NOT EXISTS idx_analytics_events_tenant_id ON analytics_events(tenant_id)`, | |
| `CREATE INDEX IF NOT EXISTS idx_analytics_events_timestamp ON analytics_events(timestamp)` | |
| ]; | |
| try { | |
| // Create tables | |
| for (const sql of createTables) { | |
| await exports.database.run(sql); | |
| } | |
| // Create indexes | |
| for (const sql of createIndexes) { | |
| await exports.database.run(sql); | |
| } | |
| console.log('Database tables and indexes created successfully'); | |
| } | |
| catch (error) { | |
| console.error('Error initializing database:', error); | |
| throw error; | |
| } | |
| } | |
| //# sourceMappingURL=database.js.map |