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 |