docfast/dist/services/database.js
openclawd 1ef8f5743c
Some checks failed
Deploy to Production / Deploy to Server (push) Failing after 20s
feat: Add built dist files with EU compliance routes
- Include compiled TypeScript with new /impressum, /privacy, /terms routes
- Temporary commit of dist files for Docker deployment
2026-02-16 13:09:25 +00:00

123 lines
4.6 KiB
JavaScript

import Database from "better-sqlite3";
import path from "path";
import { fileURLToPath } from "url";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const DB_PATH = path.join(__dirname, "../../data/docfast.db");
class DatabaseService {
db;
constructor() {
this.db = new Database(DB_PATH);
this.initialize();
}
initialize() {
// Enable WAL mode for better performance
this.db.pragma("journal_mode = WAL");
// Create tables
this.db.exec(`
CREATE TABLE IF NOT EXISTS keys (
id INTEGER PRIMARY KEY AUTOINCREMENT,
email TEXT NOT NULL,
api_key TEXT UNIQUE NOT NULL,
tier TEXT NOT NULL CHECK (tier IN ('free', 'pro')),
created_at TEXT NOT NULL,
usage_count INTEGER DEFAULT 0,
usage_month TEXT NOT NULL,
stripe_customer_id TEXT
);
CREATE INDEX IF NOT EXISTS idx_keys_api_key ON keys(api_key);
CREATE INDEX IF NOT EXISTS idx_keys_email ON keys(email);
CREATE INDEX IF NOT EXISTS idx_keys_stripe_customer_id ON keys(stripe_customer_id);
CREATE TABLE IF NOT EXISTS usage (
id INTEGER PRIMARY KEY AUTOINCREMENT,
api_key TEXT NOT NULL,
endpoint TEXT NOT NULL,
timestamp TEXT NOT NULL,
FOREIGN KEY (api_key) REFERENCES keys(api_key)
);
CREATE INDEX IF NOT EXISTS idx_usage_api_key ON usage(api_key);
CREATE INDEX IF NOT EXISTS idx_usage_timestamp ON usage(timestamp);
`);
}
// Key operations
insertKey(key) {
const stmt = this.db.prepare(`
INSERT INTO keys (email, api_key, tier, created_at, usage_count, usage_month, stripe_customer_id)
VALUES (?, ?, ?, ?, ?, ?, ?)
`);
const result = stmt.run(key.email, key.api_key, key.tier, key.created_at, key.usage_count, key.usage_month, key.stripe_customer_id || null);
return { ...key, id: result.lastInsertRowid };
}
getKeyByApiKey(apiKey) {
const stmt = this.db.prepare("SELECT * FROM keys WHERE api_key = ?");
return stmt.get(apiKey);
}
getKeyByEmail(email, tier) {
const stmt = this.db.prepare("SELECT * FROM keys WHERE email = ? AND tier = ?");
return stmt.get(email, tier);
}
getKeyByStripeCustomerId(stripeCustomerId) {
const stmt = this.db.prepare("SELECT * FROM keys WHERE stripe_customer_id = ?");
return stmt.get(stripeCustomerId);
}
updateKeyTier(apiKey, tier) {
const stmt = this.db.prepare("UPDATE keys SET tier = ? WHERE api_key = ?");
const result = stmt.run(tier, apiKey);
return result.changes > 0;
}
deleteKeyByStripeCustomerId(stripeCustomerId) {
const stmt = this.db.prepare("DELETE FROM keys WHERE stripe_customer_id = ?");
const result = stmt.run(stripeCustomerId);
return result.changes > 0;
}
getAllKeys() {
const stmt = this.db.prepare("SELECT * FROM keys");
return stmt.all();
}
// Usage operations
insertUsage(usage) {
const stmt = this.db.prepare(`
INSERT INTO usage (api_key, endpoint, timestamp)
VALUES (?, ?, ?)
`);
const result = stmt.run(usage.api_key, usage.endpoint, usage.timestamp);
return { ...usage, id: result.lastInsertRowid };
}
getUsageForKey(apiKey, fromDate, toDate) {
let query = "SELECT * FROM usage WHERE api_key = ?";
const params = [apiKey];
if (fromDate && toDate) {
query += " AND timestamp >= ? AND timestamp <= ?";
params.push(fromDate, toDate);
}
else if (fromDate) {
query += " AND timestamp >= ?";
params.push(fromDate);
}
query += " ORDER BY timestamp DESC";
const stmt = this.db.prepare(query);
return stmt.all(...params);
}
// Utility method to migrate existing JSON data
migrateFromJson(jsonKeys) {
const insertStmt = this.db.prepare(`
INSERT OR IGNORE INTO keys (email, api_key, tier, created_at, usage_count, usage_month, stripe_customer_id)
VALUES (?, ?, ?, ?, ?, ?, ?)
`);
const transaction = this.db.transaction((keys) => {
for (const key of keys) {
const currentMonth = new Date().toISOString().slice(0, 7); // YYYY-MM
insertStmt.run(key.email || "", key.key, key.tier, key.createdAt, 0, // reset usage count
currentMonth, key.stripeCustomerId || null);
}
});
transaction(jsonKeys);
}
close() {
this.db.close();
}
}
// Export singleton instance
export const db = new DatabaseService();