Merge remote-tracking branch 'upstream/dev' into feat/replace-logs

This commit is contained in:
Anish Sarkar 2026-01-14 02:04:54 +05:30
commit 99bd2df463
59 changed files with 2788 additions and 1579 deletions

View file

@ -11,7 +11,7 @@ enum ResponseType {
}
export type RequestOptions = {
method: "GET" | "POST" | "PUT" | "DELETE";
method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
headers?: Record<string, string>;
contentType?: "application/json" | "application/x-www-form-urlencoded";
signal?: AbortSignal;
@ -273,6 +273,21 @@ class BaseApiService {
});
}
async patch<T>(
url: string,
responseSchema?: ZodType<T>,
options?: Omit<RequestOptions, "method" | "responseType">
) {
return this.request(url, responseSchema, {
method: "PATCH",
headers: {
"Content-Type": "application/json",
},
...options,
responseType: ResponseType.JSON,
});
}
async getBlob(url: string, options?: Omit<RequestOptions, "method" | "responseType">) {
return this.request(url, undefined, {
...options,

View file

@ -9,6 +9,7 @@ import {
type GetDocumentRequest,
type GetDocumentsRequest,
type GetDocumentTypeCountsRequest,
type GetSurfsenseDocsRequest,
getDocumentByChunkRequest,
getDocumentByChunkResponse,
getDocumentRequest,
@ -18,6 +19,8 @@ import {
getDocumentTypeCountsRequest,
getDocumentTypeCountsResponse,
getSurfsenseDocsByChunkResponse,
getSurfsenseDocsRequest,
getSurfsenseDocsResponse,
type SearchDocumentsRequest,
searchDocumentsRequest,
searchDocumentsResponse,
@ -221,6 +224,35 @@ class DocumentsApiService {
);
};
/**
* List all Surfsense documentation documents
*/
getSurfsenseDocs = async (request: GetSurfsenseDocsRequest) => {
const parsedRequest = getSurfsenseDocsRequest.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]) => [k, String(v)])
)
: undefined;
const queryParams = transformedQueryParams
? new URLSearchParams(transformedQueryParams).toString()
: "";
const url = `/api/v1/surfsense-docs?${queryParams}`;
return baseApiService.get(url, getSurfsenseDocsResponse);
};
/**
* Update a document
*/

View file

@ -11,6 +11,7 @@ import {
getSearchSpaceResponse,
getSearchSpacesRequest,
getSearchSpacesResponse,
leaveSearchSpaceResponse,
type UpdateSearchSpaceRequest,
updateSearchSpaceRequest,
updateSearchSpaceResponse,
@ -115,6 +116,17 @@ class SearchSpacesApiService {
return baseApiService.delete(`/api/v1/searchspaces/${request.id}`, deleteSearchSpaceResponse);
};
/**
* Leave a search space (remove own membership)
* This is used by non-owners to leave a shared search space
*/
leaveSearchSpace = async (searchSpaceId: number) => {
return baseApiService.delete(
`/api/v1/searchspaces/${searchSpaceId}/members/me`,
leaveSearchSpaceResponse
);
};
}
export const searchSpacesApiService = new SearchSpacesApiService();

View file

@ -9,10 +9,17 @@ import { baseApiService } from "@/lib/apis/base-api.service";
// Types matching backend schemas
// =============================================================================
/**
* Chat visibility levels - matches backend ChatVisibility enum
*/
export type ChatVisibility = "PRIVATE" | "SEARCH_SPACE";
export interface ThreadRecord {
id: number;
title: string;
archived: boolean;
visibility: ChatVisibility;
created_by_id: string | null;
search_space_id: number;
created_at: string;
updated_at: string;
@ -35,6 +42,9 @@ export interface ThreadListItem {
id: number;
title: string;
archived: boolean;
visibility: ChatVisibility;
created_by_id: string | null;
is_own_thread: boolean;
createdAt: string;
updatedAt: string;
}
@ -127,6 +137,25 @@ export async function deleteThread(threadId: number): Promise<void> {
await baseApiService.delete(`/api/v1/threads/${threadId}`);
}
/**
* Update thread visibility (share/unshare)
*/
export async function updateThreadVisibility(
threadId: number,
visibility: ChatVisibility
): Promise<ThreadRecord> {
return baseApiService.patch<ThreadRecord>(`/api/v1/threads/${threadId}/visibility`, undefined, {
body: { visibility },
});
}
/**
* Get full thread details including visibility
*/
export async function getThreadFull(threadId: number): Promise<ThreadRecord> {
return baseApiService.get<ThreadRecord>(`/api/v1/threads/${threadId}/full`);
}
// =============================================================================
// Thread List Manager (for thread list sidebar)
// =============================================================================