Merge pull request #633 from CREDO23/feat/migrate-tojotai-tanstack-logs

[Feat] Logs | Migrate to jotai & tanstack
This commit is contained in:
Rohan Verma 2025-12-26 21:42:24 -08:00 committed by GitHub
commit 9eeecfaf4a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 447 additions and 243 deletions

View file

@ -0,0 +1,128 @@
import {
type CreateLogRequest,
createLogRequest,
createLogResponse,
type DeleteLogRequest,
deleteLogRequest,
deleteLogResponse,
type GetLogRequest,
type GetLogSummaryRequest,
type GetLogsRequest,
getLogRequest,
getLogResponse,
getLogSummaryRequest,
getLogSummaryResponse,
getLogsRequest,
getLogsResponse,
type Log,
log,
type UpdateLogRequest,
updateLogRequest,
updateLogResponse,
} from "@/contracts/types/log.types";
import { ValidationError } from "../error";
import { baseApiService } from "./base-api.service";
class LogsApiService {
/**
* Get a list of logs with optional filtering and pagination
*/
getLogs = async (request: GetLogsRequest) => {
const parsedRequest = getLogsRequest.safeParse(request);
if (!parsedRequest.success) {
console.error("Invalid request:", parsedRequest.error);
const errorMessage = parsedRequest.error.issues.map((issue) => issue.message).join(", ");
throw new ValidationError(`Invalid request: ${errorMessage}`);
}
// Transform query params to be string values
const transformedQueryParams = parsedRequest.data.queryParams
? Object.fromEntries(
Object.entries(parsedRequest.data.queryParams).map(([k, v]) => {
// Handle array values (document_type)
if (Array.isArray(v)) {
return [k, v.join(",")];
}
return [k, String(v)];
})
)
: undefined;
const queryParams = transformedQueryParams
? new URLSearchParams(transformedQueryParams).toString()
: "";
return baseApiService.get(`/api/v1/logs?${queryParams}`, getLogsResponse);
};
/**
* Get a single log by ID
*/
getLog = async (request: GetLogRequest) => {
const parsedRequest = getLogRequest.safeParse(request);
if (!parsedRequest.success) {
console.error("Invalid request:", parsedRequest.error);
const errorMessage = parsedRequest.error.issues.map((issue) => issue.message).join(", ");
throw new ValidationError(`Invalid request: ${errorMessage}`);
}
return baseApiService.get(`/api/v1/logs/${request.id}`, getLogResponse);
};
/**
* Create a log entry
*/
createLog = async (request: CreateLogRequest) => {
const parsedRequest = createLogRequest.safeParse(request);
if (!parsedRequest.success) {
console.error("Invalid request:", parsedRequest.error);
const errorMessage = parsedRequest.error.issues.map((issue) => issue.message).join(", ");
throw new ValidationError(`Invalid request: ${errorMessage}`);
}
return baseApiService.post(`/api/v1/logs`, createLogResponse, {
body: parsedRequest.data,
});
};
/**
* Update a log entry
*/
updateLog = async (logId: number, request: UpdateLogRequest) => {
const parsedRequest = updateLogRequest.safeParse(request);
if (!parsedRequest.success) {
console.error("Invalid request:", parsedRequest.error);
const errorMessage = parsedRequest.error.issues.map((issue) => issue.message).join(", ");
throw new ValidationError(`Invalid request: ${errorMessage}`);
}
return baseApiService.put(`/api/v1/logs/${logId}`, updateLogResponse, {
body: parsedRequest.data,
});
};
/**
* Delete a log entry
*/
deleteLog = async (request: DeleteLogRequest) => {
const parsedRequest = deleteLogRequest.safeParse(request);
if (!parsedRequest.success) {
console.error("Invalid request:", parsedRequest.error);
const errorMessage = parsedRequest.error.issues.map((issue) => issue.message).join(", ");
throw new ValidationError(`Invalid request: ${errorMessage}`);
}
return baseApiService.delete(`/api/v1/logs/${parsedRequest.data.id}`, deleteLogResponse);
};
/**
* Get summary for logs by search space
*/
getLogSummary = async (request: GetLogSummaryRequest) => {
const parsedRequest = getLogSummaryRequest.safeParse(request);
if (!parsedRequest.success) {
console.error("Invalid request:", parsedRequest.error);
const errorMessage = parsedRequest.error.issues.map((issue) => issue.message).join(", ");
throw new ValidationError(`Invalid request: ${errorMessage}`);
}
const { search_space_id, hours } = parsedRequest.data;
const url = `/api/v1/logs/search-space/${search_space_id}/summary${hours ? `?hours=${hours}` : ""}`;
return baseApiService.get(url, getLogSummaryResponse);
};
}
export const logsApiService = new LogsApiService();

View file

@ -1,4 +1,5 @@
import type { GetDocumentsRequest } from "@/contracts/types/document.types";
import type { GetLogsRequest } from "@/contracts/types/log.types";
import type { GetSearchSpacesRequest } from "@/contracts/types/search-space.types";
export const cacheKeys = {
@ -18,6 +19,13 @@ export const cacheKeys = {
typeCounts: (searchSpaceId?: string) => ["documents", "type-counts", searchSpaceId] as const,
byChunk: (chunkId: string) => ["documents", "by-chunk", chunkId] as const,
},
logs: {
list: (searchSpaceId?: number | string) => ["logs", "list", searchSpaceId] as const,
detail: (logId: number | string) => ["logs", "detail", logId] as const,
summary: (searchSpaceId?: number | string) => ["logs", "summary", searchSpaceId] as const,
withQueryParams: (queries: GetLogsRequest["queryParams"]) =>
["logs", "with-query-params", ...(queries ? Object.values(queries) : [])] as const,
},
newLLMConfigs: {
all: (searchSpaceId: number) => ["new-llm-configs", searchSpaceId] as const,
byId: (configId: number) => ["new-llm-configs", "detail", configId] as const,