LOKVDNBE475AI42AEO2LKK6EQKA5GGSZTS6VWJEQBV23E4TWTFCAC
JEWGR3YVTBR536L6UPKSFD54CCCU23G3G723LKRESPRVYXIZAWAAC
XB55XTJNPMST6UAIBIG6V5PHMHRAHGZ5AY7G6VSVW6GGVXTKS2VAC
MQEF3A535WLHGV7UIT3F5V6WQKPSWNVKH2WRSXO67FXZJM6LHBFQC
OBXY6BHNROIV7W4O3MMQ6GTQXU2XUKF5A4DCJYDLUEUHV72E7BNAC
ONSQYCF6NFUEA24ORB62W4P62LKUMV7C5PLYRZQULHFDNROEY2HQC
TGGXF43HKM7KPF4OS4ANJTSSS3LKMJKPXL7PLY5CZJGIFQW4CQYAC
ST5WLNWFS4AOVPOJHMREC4VGXQMIDRDLBZ2M4FCE5FPKLPQTUTRQC
TKCG7EZ3MYG2FFWYRLGQTQXIRDSNGICDHK6CE6OZJPTBK6CNYFJAC
/**
* Standardized logging utilities for consistent log formatting
*/
/**
* Log levels for different types of operations
*/
export enum LogLevel {
ERROR = 'ERROR',
WARN = 'WARN',
INFO = 'INFO',
DEBUG = 'DEBUG'
}
/**
* Standard log entry structure
*/
interface LogEntry {
level: LogLevel;
operation: string;
userId?: string;
resourceType?: string;
resourceId?: string;
details?: Record<string, unknown> | undefined;
error?: Error | string;
}
/**
* Formats a log entry consistently
*/
function formatLogEntry(entry: LogEntry): string {
const timestamp = new Date().toISOString();
const parts = [`[${timestamp}]`, `[${entry.level}]`, entry.operation];
if (entry.userId) {
parts.push(`user:${entry.userId}`);
}
if (entry.resourceType && entry.resourceId) {
parts.push(`${entry.resourceType}:${entry.resourceId}`);
}
if (entry.details && Object.keys(entry.details).length > 0) {
parts.push(JSON.stringify(entry.details));
}
return parts.join(' ');
}
/**
* Logs CRUD operations with standardized format
*/
export function logCrudOperation(
operation: 'CREATE' | 'UPDATE' | 'DELETE',
resourceType: string,
resourceId: string,
userId: string,
details?: Record<string, unknown>
): void {
const entry: LogEntry = {
level: LogLevel.INFO,
operation,
userId,
resourceType,
resourceId,
details
};
console.info(formatLogEntry(entry));
}
/**
* Logs authentication/authorization events
*/
export function logAuthEvent(
event: string,
userId: string,
details?: Record<string, unknown>
): void {
const entry: LogEntry = {
level: LogLevel.INFO,
operation: 'AUTH',
userId,
details: { event, ...details }
};
console.info(formatLogEntry(entry));
}
/**
* Logs errors with context
*/
export function logError(
operation: string,
error: Error | string,
context?: Record<string, unknown>
): void {
const entry: LogEntry = {
level: LogLevel.ERROR,
operation,
error,
details: context
};
console.error(formatLogEntry(entry), error);
}
/**
* Logs debug information (only in development)
*/
export function logDebug(
operation: string,
details: Record<string, unknown>
): void {
// Only log debug in development environments
if (process.env.NODE_ENV === 'development') {
const entry: LogEntry = {
level: LogLevel.DEBUG,
operation,
details
};
console.debug(formatLogEntry(entry));
}
}
export function transformCallRateRows(rows: any[]): import("./types").CallRateRow[] {
return rows.map(row => ({
hour_of_day: Number(row.hour_of_day),
call_count: Number(row.call_count),
total_recording_hours: Number(row.total_recording_hours),
call_rate_per_hour: Number(row.call_rate_per_hour)
}));
export function transformCallRateRows(rows: unknown[]): import("./types").CallRateRow[] {
return rows.map(row => {
const r = row as Record<string, unknown>;
return {
hour_of_day: Number(r.hour_of_day),
call_count: Number(r.call_count),
total_recording_hours: Number(r.total_recording_hours),
call_rate_per_hour: Number(r.call_rate_per_hour)
};
});
export function transformSpeciesRows(rows: any[]): import("./types").SpeciesRow[] {
return rows.map(row => ({
id: row.id as string,
label: row.label as string,
ebird_code: row.ebird_code as string | null
}));
export function transformSpeciesRows(rows: unknown[]): import("./types").SpeciesRow[] {
return rows.map(row => {
const r = row as Record<string, unknown>;
return {
id: r.id as string,
label: r.label as string,
ebird_code: r.ebird_code as string | null
};
});
export function transformCallTypeRows(rows: any[]): import("./types").CallTypeRow[] {
return rows.map(row => ({
id: row.id as string,
label: row.label as string
}));
export function transformCallTypeRows(rows: unknown[]): import("./types").CallTypeRow[] {
return rows.map(row => {
const r = row as Record<string, unknown>;
return {
id: r.id as string,
label: r.label as string
};
});
export function transformFilterRows(rows: any[]): import("./types").FilterRow[] {
return rows.map(row => ({
id: row.id as string,
name: row.name as string
}));
export function transformFilterRows(rows: unknown[]): import("./types").FilterRow[] {
return rows.map(row => {
const r = row as Record<string, unknown>;
return {
id: r.id as string,
name: r.name as string
};
});
export async function getClusterDataset(db: any, clusterId: string) {
return db.execute(sql`
SELECT dataset_id FROM cluster WHERE id = ${clusterId} AND active = true
`);
export async function getClusterDataset(db: Database, clusterId: string) {
return db
.select({ dataset_id: cluster.datasetId })
.from(cluster)
.where(and(eq(cluster.id, clusterId), eq(cluster.active, true)))
.limit(1);
// Build filter conditions
let whereConditions = sqlExpr`${file.clusterId} = ${clusterId} AND ${file.active} = true`;
// Build filter conditions using Drizzle ORM
const baseConditions = [
eq(file.clusterId, clusterId),
eq(file.active, true)
];