151 lines
3.6 KiB
TypeScript
151 lines
3.6 KiB
TypeScript
import { Kysely, SqliteDialect } from 'kysely';
|
|
import SQLite from 'better-sqlite3';
|
|
import path from 'path';
|
|
import fs from 'fs';
|
|
|
|
export interface SessionTable {
|
|
id: string;
|
|
url: string;
|
|
status: string;
|
|
seed: number;
|
|
max_states: number;
|
|
states_visited: number;
|
|
anomalies_found: number;
|
|
started_at: number;
|
|
finished_at: number | null;
|
|
config_json: string;
|
|
}
|
|
|
|
export interface StateTable {
|
|
id: string;
|
|
session_id: string;
|
|
url: string;
|
|
title: string;
|
|
dom_snapshot_path: string | null;
|
|
visit_count: number;
|
|
discovered_at: number;
|
|
}
|
|
|
|
export interface ActionTable {
|
|
id: string;
|
|
session_id: string;
|
|
state_id: string;
|
|
type: string;
|
|
selector: string | null;
|
|
value: string | null;
|
|
url: string | null;
|
|
seed: number;
|
|
executed_at: number;
|
|
sequence_order: number;
|
|
}
|
|
|
|
export interface AnomalyTable {
|
|
id: string;
|
|
session_id: string;
|
|
type: string;
|
|
severity: string;
|
|
description: string;
|
|
action_trace_json: string;
|
|
evidence_json: string;
|
|
screenshot_path: string | null;
|
|
dom_snapshot_path: string | null;
|
|
detected_at: number;
|
|
ai_enrichment_json: string | null;
|
|
ai_enriched_at: number | null;
|
|
browser: string | null;
|
|
browser_version: string | null;
|
|
}
|
|
|
|
export interface NotificationTable {
|
|
id: string;
|
|
anomaly_id: string;
|
|
channel: string;
|
|
status: string;
|
|
sent_at: number | null;
|
|
error: string | null;
|
|
}
|
|
|
|
export interface ScheduleTable {
|
|
id: string;
|
|
name: string;
|
|
url: string;
|
|
config_json: string;
|
|
cron_expression: string;
|
|
enabled: number;
|
|
last_run_at: number | null;
|
|
next_run_at: number | null;
|
|
created_at: number;
|
|
}
|
|
|
|
export interface VisualBaselineTable {
|
|
id: string;
|
|
state_id: string;
|
|
url: string;
|
|
screenshot_path: string;
|
|
approved_at: number;
|
|
approved_by: string | null;
|
|
width: number;
|
|
height: number;
|
|
}
|
|
|
|
export interface VisualComparisonTable {
|
|
id: string;
|
|
session_id: string;
|
|
state_id: string;
|
|
baseline_id: string | null;
|
|
current_screenshot_path: string;
|
|
diff_screenshot_path: string | null;
|
|
diff_pixels: number | null;
|
|
diff_percent: number | null;
|
|
status: string;
|
|
created_at: number;
|
|
}
|
|
|
|
export interface PerformanceMetricTable {
|
|
id: string;
|
|
session_id: string;
|
|
state_id: string;
|
|
url: string;
|
|
ttfb: number | null;
|
|
dom_content_loaded: number | null;
|
|
load_complete: number | null;
|
|
lcp: number | null;
|
|
cls: number | null;
|
|
fid: number | null;
|
|
inp: number | null;
|
|
total_requests: number | null;
|
|
failed_requests: number | null;
|
|
total_transfer_size: number | null;
|
|
captured_at: number;
|
|
}
|
|
|
|
export interface Database {
|
|
sessions: SessionTable;
|
|
states: StateTable;
|
|
actions: ActionTable;
|
|
anomalies: AnomalyTable;
|
|
notifications: NotificationTable;
|
|
schedules: ScheduleTable;
|
|
visual_baselines: VisualBaselineTable;
|
|
visual_comparisons: VisualComparisonTable;
|
|
performance_metrics: PerformanceMetricTable;
|
|
}
|
|
|
|
export function createDatabase(config: { driver: string; path: string; url?: string }): Kysely<Database> {
|
|
if (config.driver === 'postgres') {
|
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
const { Pool } = require('pg') as { Pool: new (opts: { connectionString?: string }) => unknown };
|
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
const { PostgresDialect } = require('kysely') as { PostgresDialect: new (opts: { pool: unknown }) => SqliteDialect };
|
|
return new Kysely<Database>({
|
|
dialect: new PostgresDialect({ pool: new Pool({ connectionString: config.url }) }),
|
|
});
|
|
}
|
|
|
|
fs.mkdirSync(path.dirname(config.path), { recursive: true });
|
|
|
|
return new Kysely<Database>({
|
|
dialect: new SqliteDialect({ database: new SQLite(config.path) }),
|
|
});
|
|
}
|