@kanadi/core
Version:
Multi-Layer CAPTCHA Framework with customizable validators and challenge bundles
70 lines (62 loc) • 1.61 kB
text/typescript
import { sql } from "bun";
export interface KanadiHistory {
id: string;
device_id: string;
session_id: string;
created_at: Date;
}
export class HistoryRepository {
async create(data: {
deviceId: string;
sessionId: string;
}): Promise<KanadiHistory> {
const result = await sql`
INSERT INTO kanadi_history (device_id, session_id)
VALUES (${data.deviceId}, ${data.sessionId})
RETURNING *
`;
return result[0] as KanadiHistory;
}
async findByDeviceId(deviceId: string, limit: number = 100): Promise<KanadiHistory[]> {
const result = await sql`
SELECT * FROM kanadi_history
WHERE device_id = ${deviceId}
ORDER BY created_at DESC
LIMIT ${limit}
`;
return result as KanadiHistory[];
}
async findBySessionId(sessionId: string): Promise<KanadiHistory[]> {
const result = await sql`
SELECT * FROM kanadi_history
WHERE session_id = ${sessionId}
ORDER BY created_at DESC
`;
return result as KanadiHistory[];
}
async getStats(): Promise<{
total: number;
today: number;
}> {
const totalResult = await sql`
SELECT COUNT(*) as count FROM kanadi_history
`;
const todayResult = await sql`
SELECT COUNT(*) as count
FROM kanadi_history
WHERE created_at >= CURRENT_DATE
`;
return {
total: Number(totalResult[0]?.count || 0),
today: Number(todayResult[0]?.count || 0),
};
}
async deleteOld(days: number = 30): Promise<number> {
const result = await sql`
DELETE FROM kanadi_history
WHERE created_at < CURRENT_TIMESTAMP - INTERVAL '${sql.raw(days.toString())} days'
RETURNING id
`;
return result.length;
}
}