@kanadi/core
Version:
Multi-Layer CAPTCHA Framework with customizable validators and challenge bundles
75 lines (68 loc) • 1.61 kB
text/typescript
import { sql } from "bun";
export interface KanadiContext {
id: string;
session_id: string;
user_id: string;
bundle_id?: string;
ip: string;
user_agent: string;
referrer?: string;
created_at: Date;
updated_at: Date;
}
export class ContextRepository {
async create(data: {
sessionId: string;
userId: string;
bundleId?: string;
ip: string;
userAgent: string;
referrer?: string;
}): Promise<KanadiContext> {
const result = await sql`
INSERT INTO kanadi_contexts (session_id, user_id, bundle_id, ip, user_agent, referrer)
VALUES (
${data.sessionId},
${data.userId},
${data.bundleId || null},
${data.ip},
${data.userAgent},
${data.referrer || null}
)
RETURNING *
`;
return result[0] as KanadiContext;
}
async findBySessionId(sessionId: string): Promise<KanadiContext | null> {
const result = await sql`
SELECT * FROM kanadi_contexts
WHERE session_id = ${sessionId}
LIMIT 1
`;
return result.length > 0 ? (result[0] as KanadiContext) : null;
}
async updateBundleId(sessionId: string, bundleId: string): Promise<void> {
await sql`
UPDATE kanadi_contexts
SET bundle_id = ${bundleId}
WHERE session_id = ${sessionId}
`;
}
async getStats(): Promise<{
total: number;
today: number;
}> {
const totalResult = await sql`
SELECT COUNT(*) as count FROM kanadi_contexts
`;
const todayResult = await sql`
SELECT COUNT(*) as count
FROM kanadi_contexts
WHERE created_at >= CURRENT_DATE
`;
return {
total: Number(totalResult[0]?.count || 0),
today: Number(todayResult[0]?.count || 0),
};
}
}