short-url/lib/db.ts

74 lines
2.2 KiB
TypeScript
Raw Normal View History

2024-11-26 12:45:06 +08:00
import Database from 'better-sqlite3';
import { nanoid } from 'nanoid';
2024-11-29 20:46:12 +08:00
import path from 'path';
2024-11-26 12:45:06 +08:00
2024-11-30 08:19:57 +08:00
const dataDir = 'data'
2024-11-29 20:46:12 +08:00
const dbPath = path.join(dataDir, 'shorturl.db');
const db = new Database(dbPath);
2024-11-26 12:45:06 +08:00
// 创建表(如果不存在)
db.exec(`
CREATE TABLE IF NOT EXISTS urls (
id INTEGER PRIMARY KEY AUTOINCREMENT,
short_code TEXT UNIQUE,
long_url TEXT NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
visits INTEGER DEFAULT 0,
expires_at DATETIME
)
`);
// 定义接口
interface UrlResult {
long_url: string;
expires_at: string | null;
}
interface UrlStats {
visits: number;
expires_at: string | null;
}
// 创建短链接
export function createShortUrl(longUrl: string, expiresIn: number): string {
const shortCode = nanoid(6);
const expiresAt = expiresIn === 0 ? null : new Date(Date.now() + expiresIn * 1000).toISOString();
const stmt = db.prepare('INSERT INTO urls (short_code, long_url, expires_at) VALUES (?, ?, ?)');
stmt.run(shortCode, longUrl, expiresAt);
return shortCode;
}
// 获取长链接
export function getLongUrl(shortCode: string): { longUrl: string | null, expired: boolean } {
const stmt = db.prepare('SELECT long_url, expires_at FROM urls WHERE short_code = ?');
const result: UrlResult | undefined = stmt.get(shortCode) as UrlResult | undefined;
if (!result) {
return { longUrl: null, expired: false };
}
if (result.expires_at === null) {
db.prepare('UPDATE urls SET visits = visits + 1 WHERE short_code = ?').run(shortCode);
return { longUrl: result.long_url, expired: false };
}
const now = new Date();
const expiresAt = new Date(result.expires_at);
if (expiresAt < now) {
return { longUrl: null, expired: true };
}
db.prepare('UPDATE urls SET visits = visits + 1 WHERE short_code = ?').run(shortCode);
return { longUrl: result.long_url, expired: false };
}
// 获取链接统计信息
export function getUrlStats(shortCode: string): { visits: number, expiresAt: string | null } | null {
const stmt = db.prepare('SELECT visits, expires_at FROM urls WHERE short_code = ?');
const result: UrlStats | undefined = stmt.get(shortCode) as UrlStats | undefined;
return result ? { visits: result.visits, expiresAt: result.expires_at } : null;
}