@smartsamurai/krapi-sdk
Version:
KRAPI TypeScript SDK - Easy-to-use client SDK for connecting to self-hosted KRAPI servers (like Appwrite SDK)
169 lines (156 loc) • 5.55 kB
text/typescript
/**
* Activity Adapter
*
* Unifies ActivityHttpClient and ActivityLogger behind a common interface.
*/
import { ActivityLogger, ActivityLog } from "../../activity-logger";
import { ActivityHttpClient } from "../../http-clients/activity-http-client";
import { createAdapterInitError } from "./error-handler";
type Mode = "client" | "server";
export class ActivityAdapter {
private mode: Mode;
private httpClient: ActivityHttpClient | undefined;
private logger: ActivityLogger | undefined;
constructor(mode: Mode, httpClient?: ActivityHttpClient, logger?: ActivityLogger) {
this.mode = mode;
this.httpClient = httpClient;
this.logger = logger;
}
async log(activityData: Omit<ActivityLog, "id" | "timestamp">): Promise<ActivityLog> {
if (this.mode === "client") {
if (!this.httpClient) {
throw createAdapterInitError("HTTP client", this.mode);
}
const response = await this.httpClient.log(activityData);
return (response.data as ActivityLog) || ({} as ActivityLog);
} else {
if (!this.logger) {
throw createAdapterInitError("Activity logger", this.mode);
}
return await this.logger.log(activityData);
}
}
async query(query: {
user_id?: string;
project_id?: string;
action?: string;
resource_type?: string;
resource_id?: string;
severity?: string;
start_date?: Date;
end_date?: Date;
limit?: number;
offset?: number;
}): Promise<ActivityLog[]> {
if (this.mode === "client") {
if (!this.httpClient) {
throw createAdapterInitError("HTTP client", this.mode);
}
// HTTP client accepts ActivityQuery with Date types
const response = await this.httpClient.query(query);
const data = response.data;
// Handle different response formats
if (data && typeof data === "object") {
// If response has 'data' field (PaginatedResponse format)
if ("data" in data && Array.isArray(data.data)) {
return data.data as ActivityLog[];
}
// If response has 'logs' field
if ("logs" in data && Array.isArray(data.logs)) {
return data.logs as ActivityLog[];
}
// If response is directly an array
if (Array.isArray(data)) {
return data as ActivityLog[];
}
}
// Return empty array if no valid data found
return [];
} else {
if (!this.logger) {
throw createAdapterInitError("Activity logger", this.mode);
}
const result = await this.logger.query(query);
return result.logs || [];
}
}
async getStats(projectId?: string, days?: number): Promise<{
total_actions: number;
actions_by_type: Record<string, number>;
actions_by_severity: Record<string, number>;
actions_by_user: Record<string, number>;
}> {
if (this.mode === "client") {
if (!this.httpClient) {
throw createAdapterInitError("HTTP client", this.mode);
}
const response = await this.httpClient.getStats(projectId, days);
return response.data || {
total_actions: 0,
actions_by_type: {},
actions_by_severity: {},
actions_by_user: {},
};
} else {
if (!this.logger) {
throw createAdapterInitError("Activity logger", this.mode);
}
const stats = await this.logger.getActivityStats(projectId, days);
return {
total_actions: stats.total_actions || 0,
actions_by_type: stats.actions_by_type || {},
actions_by_severity: stats.actions_by_severity || {},
actions_by_user: stats.actions_by_user || {},
};
}
}
async getRecent(projectId?: string, limit?: number): Promise<ActivityLog[]> {
if (this.mode === "client") {
if (!this.httpClient) {
throw createAdapterInitError("HTTP client", this.mode);
}
// HTTP client getRecent expects (userId?, projectId?, limit)
const response = await this.httpClient.getRecent(undefined, projectId, limit);
const data = response.data;
// Handle different response formats
if (data && typeof data === "object") {
// If response has 'data' field
if ("data" in data && Array.isArray(data.data)) {
return data.data as ActivityLog[];
}
// If response has 'logs' field
if ("logs" in data && Array.isArray(data.logs)) {
return data.logs as ActivityLog[];
}
// If response is directly an array
if (Array.isArray(data)) {
return data as ActivityLog[];
}
}
// Return empty array if no valid data found
return [];
} else {
if (!this.logger) {
throw createAdapterInitError("Activity logger", this.mode);
}
const recent = await this.logger.getRecentActivity(undefined, projectId, limit);
return recent || [];
}
}
async cleanup(daysToKeep?: number): Promise<{ success: boolean; deleted_count: number }> {
if (this.mode === "client") {
if (!this.httpClient) {
throw createAdapterInitError("HTTP client", this.mode);
}
const response = await this.httpClient.cleanup(daysToKeep);
return response.data || { success: false, deleted_count: 0 };
} else {
if (!this.logger) {
throw createAdapterInitError("Activity logger", this.mode);
}
// For server mode, implement cleanup in ActivityLogger
const result = await this.logger.cleanup(daysToKeep);
return result;
}
}
}