Files
dbx/apps/desktop/src/lib/http.ts
T

993 lines
31 KiB
TypeScript

import type {
ConnectionConfig,
DatabaseInfo,
TableInfo,
ObjectInfo,
ObjectSource,
ObjectSourceKind,
ColumnInfo,
IndexInfo,
ForeignKeyInfo,
TriggerInfo,
QueryResult,
SqlReferenceAnalysis,
InstalledPlugin,
JdbcDriverInfo,
JdbcPluginStatus,
SidebarLayout,
SavedSqlFile,
SavedSqlFolder,
SavedSqlLibrary,
} from "@/types/database";
import type { AiConfig } from "@/stores/settingsStore";
import type {
AgentDriverInfo,
AiCompletionRequest,
AiStreamChunk,
AiConversation,
AiModelInfo,
DesktopSettings,
DriverInstallProgress,
JavaRuntimeConfig,
UpdateInfo,
RedisDatabaseInfo,
RedisValue,
RedisScanResult,
RedisCommandResult,
MongoDocumentResult,
HistoryEntry,
SqlFileRequest,
SqlFilePreview,
SqlFileProgress,
TransferRequest,
TransferProgress,
TableImportPreview,
TableImportRequest,
TableImportSummary,
TableImportProgress,
DatabaseExportRequest,
ExportProgress,
XlsxCellValue,
} from "./tauri";
import type { QueryEditability } from "@/lib/sqlAnalysis";
import type { DataGridSaveStatementOptions } from "@/lib/dataGridSql";
import type { DataGridSavePreparation } from "./tauri";
// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------
async function post<T>(url: string, body: unknown): Promise<T> {
const res = await fetch(url, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(body),
});
if (!res.ok) throw new Error(await res.text());
return res.json();
}
async function get<T>(url: string): Promise<T> {
const res = await fetch(url);
if (!res.ok) throw new Error(await res.text());
return res.json();
}
async function del<T>(url: string): Promise<T> {
const res = await fetch(url, { method: "DELETE" });
if (!res.ok) throw new Error(await res.text());
return res.json();
}
function qs(params: Record<string, string | number | undefined>): string {
const sp = new URLSearchParams();
for (const [k, v] of Object.entries(params)) {
if (v !== undefined && v !== null) sp.set(k, String(v));
}
return sp.toString();
}
// ---------------------------------------------------------------------------
// Connection
// ---------------------------------------------------------------------------
export async function testConnection(config: ConnectionConfig): Promise<string> {
return post("/api/connection/test", { config });
}
export async function connectDb(config: ConnectionConfig): Promise<string> {
return post("/api/connection/connect", { config });
}
export async function disconnectDb(connectionId: string): Promise<void> {
return post("/api/connection/disconnect", { connectionId });
}
export async function saveConnections(configs: ConnectionConfig[]): Promise<void> {
return post("/api/connection/save", { configs });
}
export async function loadConnections(): Promise<ConnectionConfig[]> {
return get("/api/connection/list");
}
export async function listSystemFonts(): Promise<string[]> {
return [];
}
export async function listPlugins(): Promise<InstalledPlugin[]> {
return get("/api/plugins");
}
export async function listJdbcDrivers(): Promise<JdbcDriverInfo[]> {
return [];
}
export async function importJdbcDrivers(_paths: string[]): Promise<JdbcDriverInfo[]> {
return [];
}
export async function deleteJdbcDriver(_path: string): Promise<JdbcDriverInfo[]> {
return [];
}
export async function jdbcPluginStatus(): Promise<JdbcPluginStatus> {
return {
installed: false,
version: null,
protocol_version: null,
compatible: true,
latest_version: null,
latest_protocol_version: null,
update_available: false,
path: "",
};
}
export async function installJdbcPlugin(): Promise<JdbcPluginStatus> {
return jdbcPluginStatus();
}
export async function installJdbcPluginLocal(_path: string): Promise<JdbcPluginStatus> {
return jdbcPluginStatus();
}
export async function uninstallJdbcPlugin(): Promise<JdbcPluginStatus> {
return jdbcPluginStatus();
}
export async function listInstalledAgentsLocal(): Promise<AgentDriverInfo[]> {
return get("/api/agents/installed-local");
}
export async function listInstalledAgents(): Promise<AgentDriverInfo[]> {
return get("/api/agents/installed");
}
export async function installAgent(dbType: string): Promise<void> {
await post("/api/agents/install", { dbType });
}
export async function upgradeAllAgents(): Promise<number> {
const result: { count: number } = await post("/api/agents/upgrade-all", {});
return result.count;
}
export async function uninstallAgent(dbType: string): Promise<void> {
await post("/api/agents/uninstall", { dbType });
}
export async function getAgentJavaRuntimeConfig(): Promise<JavaRuntimeConfig> {
return get("/api/agents/java-runtime");
}
export async function setAgentJavaRuntimeConfig(config: JavaRuntimeConfig): Promise<JavaRuntimeConfig> {
return post("/api/agents/java-runtime", { config });
}
export async function invalidateAgentRegistryCache(): Promise<void> {
await post("/api/agents/invalidate-registry-cache", {});
}
export async function importAgentsFromZip(fileOrPath: string | File): Promise<number> {
if (typeof fileOrPath === "string") {
throw new Error("Offline ZIP import in web mode requires a File object, not a file path");
}
const formData = new FormData();
formData.append("file", fileOrPath);
const res = await fetch("/api/agents/import-offline", { method: "POST", body: formData });
if (!res.ok) throw new Error(await res.text());
const result: { count: number } = await res.json();
return result.count;
}
export async function importAgentJar(_dbType: string, _path: string): Promise<void> {
throw new Error("Local JAR import is only available in the desktop app");
}
export async function reinstallJre(jreKey?: string): Promise<void> {
await post("/api/agents/reinstall-jre", { jreKey });
}
export async function uninstallJre(jreKey: string): Promise<void> {
await post("/api/agents/uninstall-jre", { jreKey });
}
export async function listenAgentInstallProgress(
handler: (progress: DriverInstallProgress) => void,
): Promise<() => void> {
const es = new EventSource("/api/agents/progress/global");
es.onmessage = (event) => {
try {
handler(JSON.parse(event.data));
} catch {
/* ignore malformed progress events */
}
};
return () => es.close();
}
export async function loadSavedSqlLibrary(): Promise<SavedSqlLibrary> {
return get("/api/saved-sql");
}
export async function saveSavedSqlFolder(folder: SavedSqlFolder): Promise<SavedSqlFolder> {
return post("/api/saved-sql/folders", folder);
}
export async function deleteSavedSqlFolder(id: string): Promise<void> {
return del(`/api/saved-sql/folders/${encodeURIComponent(id)}`);
}
export async function saveSavedSqlFile(file: SavedSqlFile): Promise<SavedSqlFile> {
return post("/api/saved-sql", file);
}
export async function deleteSavedSqlFile(id: string): Promise<void> {
return del(`/api/saved-sql/${encodeURIComponent(id)}`);
}
// ---------------------------------------------------------------------------
// Schema
// ---------------------------------------------------------------------------
export async function listDatabases(connectionId: string): Promise<DatabaseInfo[]> {
return get(`/api/schema/databases?${qs({ connection_id: connectionId })}`);
}
export async function saveSchemaCache(cacheKey: string, payload: unknown): Promise<void> {
return post("/api/schema/cache", { cacheKey, payload });
}
export async function loadSchemaCache<T = unknown>(cacheKey: string): Promise<T | null> {
return get(`/api/schema/cache?${qs({ cache_key: cacheKey })}`);
}
export async function deleteSchemaCachePrefix(prefix: string): Promise<void> {
return del(`/api/schema/cache-prefix?${qs({ prefix })}`);
}
export async function listSchemas(connectionId: string, database: string): Promise<string[]> {
return get(`/api/schema/schemas?${qs({ connection_id: connectionId, database })}`);
}
export async function listTables(
connectionId: string,
database: string,
schema: string,
filter?: string,
limit?: number,
): Promise<TableInfo[]> {
return get(`/api/schema/tables?${qs({ connection_id: connectionId, database, schema, filter, limit })}`);
}
export async function listObjects(connectionId: string, database: string, schema: string): Promise<ObjectInfo[]> {
return get(`/api/schema/objects?${qs({ connection_id: connectionId, database, schema })}`);
}
export async function getObjectSource(
connectionId: string,
database: string,
schema: string,
name: string,
objectType: ObjectSourceKind,
): Promise<ObjectSource> {
return get(
`/api/schema/object-source?${qs({ connection_id: connectionId, database, schema, table: name, object_type: objectType })}`,
);
}
export async function getColumns(
connectionId: string,
database: string,
schema: string,
table: string,
): Promise<ColumnInfo[]> {
return get(`/api/schema/columns?${qs({ connection_id: connectionId, database, schema, table })}`);
}
export async function listIndexes(
connectionId: string,
database: string,
schema: string,
table: string,
): Promise<IndexInfo[]> {
return get(`/api/schema/indexes?${qs({ connection_id: connectionId, database, schema, table })}`);
}
export async function listForeignKeys(
connectionId: string,
database: string,
schema: string,
table: string,
): Promise<ForeignKeyInfo[]> {
return get(`/api/schema/foreign-keys?${qs({ connection_id: connectionId, database, schema, table })}`);
}
export async function listTriggers(
connectionId: string,
database: string,
schema: string,
table: string,
): Promise<TriggerInfo[]> {
return get(`/api/schema/triggers?${qs({ connection_id: connectionId, database, schema, table })}`);
}
export async function getTableDdl(
connectionId: string,
database: string,
schema: string,
table: string,
): Promise<string> {
return get(`/api/schema/ddl?${qs({ connection_id: connectionId, database, schema, table })}`);
}
// ---------------------------------------------------------------------------
// Query
// ---------------------------------------------------------------------------
export async function executeQuery(
connectionId: string,
database: string,
sql: string,
schema?: string,
executionId?: string,
options?: { maxRows?: number; fetchSize?: number; pageSize?: number; resultSessionId?: string },
): Promise<QueryResult> {
return post("/api/query/execute", { connectionId, database, sql, schema, executionId, ...options });
}
export async function executeMulti(
connectionId: string,
database: string,
sql: string,
schema?: string,
executionId?: string,
options?: { maxRows?: number; fetchSize?: number; pageSize?: number; resultSessionId?: string },
): Promise<QueryResult[]> {
return post("/api/query/execute-multi", { connectionId, database, sql, schema, executionId, ...options });
}
export async function closeQuerySession(connectionId: string, database: string, sessionId: string): Promise<boolean> {
return post("/api/query/close-session", { connectionId, database, sessionId });
}
export async function executeBatch(
connectionId: string,
database: string,
statements: string[],
schema?: string,
): Promise<QueryResult> {
return post("/api/query/execute-batch", { connectionId, database, statements, schema });
}
export async function executeScript(
connectionId: string,
database: string,
sql: string,
schema?: string,
): Promise<QueryResult> {
return post("/api/query/execute-script", { connectionId, database, sql, schema });
}
export async function executeInTransaction(
connectionId: string,
database: string,
statements: string[],
schema?: string,
): Promise<QueryResult> {
return post("/api/query/execute-in-transaction", { connectionId, database, statements, schema });
}
export async function cancelQuery(executionId: string): Promise<boolean> {
return post("/api/query/cancel", { executionId });
}
export async function analyzeSqlReferences(sql: string, dialect?: string): Promise<SqlReferenceAnalysis> {
return post("/api/query/analyze-sql-references", { sql, dialect });
}
export async function analyzeEditableQueryEditability(sql: string): Promise<QueryEditability> {
return post("/api/query/analyze-editability", { sql });
}
export async function prepareDataGridSave(options: DataGridSaveStatementOptions): Promise<DataGridSavePreparation> {
return post("/api/query/prepare-data-grid-save", { options });
}
// ---------------------------------------------------------------------------
// AI
// ---------------------------------------------------------------------------
export async function aiComplete(request: AiCompletionRequest): Promise<string> {
return post("/api/ai/complete", { request });
}
export async function aiStream(
sessionId: string,
request: AiCompletionRequest,
onChunk: (chunk: AiStreamChunk) => void,
): Promise<void> {
const res = await fetch("/api/ai/stream", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ session_id: sessionId, request }),
});
if (!res.ok) throw new Error(await res.text());
const reader = res.body!.getReader();
const decoder = new TextDecoder();
let buffer = "";
while (true) {
const { done, value } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
const lines = buffer.split("\n");
buffer = lines.pop() || "";
for (const line of lines) {
if (line.startsWith("data:")) {
const data = line.slice(5).trim();
if (data && data !== "[DONE]") {
try {
const chunk: AiStreamChunk = JSON.parse(data);
onChunk(chunk);
if (chunk.done) return;
} catch {
// skip malformed JSON
}
}
}
}
}
}
export async function aiCancelStream(sessionId: string): Promise<boolean> {
return post("/api/ai/cancel-stream", { sessionId });
}
export async function aiTestConnection(config: AiConfig): Promise<string> {
return post("/api/ai/test-connection", { config });
}
export async function aiListModels(config: AiConfig): Promise<AiModelInfo[]> {
return post("/api/ai/models", { config });
}
export async function saveAiConfig(config: AiConfig): Promise<void> {
return post("/api/ai/config", { config });
}
export async function loadAiConfig(): Promise<AiConfig | null> {
return get("/api/ai/config");
}
export async function loadDesktopSettings(): Promise<DesktopSettings> {
return { show_tray_icon: true };
}
export async function saveDesktopSettings(_settings: DesktopSettings): Promise<void> {
return;
}
export async function loadPinnedTreeNodeIds(): Promise<string[]> {
return get("/api/app-settings/pinned-tree-node-ids");
}
export async function savePinnedTreeNodeIds(_ids: string[]): Promise<void> {
return post("/api/app-settings/pinned-tree-node-ids", { ids: _ids });
}
// --- AI Conversations ---
export async function saveAiConversation(conversation: AiConversation): Promise<void> {
return post("/api/ai/conversation", { conversation });
}
export async function loadAiConversations(): Promise<AiConversation[]> {
return get("/api/ai/conversations");
}
export async function deleteAiConversation(id: string): Promise<void> {
return del(`/api/ai/conversation/${id}`);
}
// ---------------------------------------------------------------------------
// SQL File Execution
// ---------------------------------------------------------------------------
export async function previewSqlFile(fileOrPath: string | File): Promise<SqlFilePreview> {
if (typeof fileOrPath === "string") {
// In web mode a raw path is not useful; throw a clear error
throw new Error("previewSqlFile in web mode requires a File object, not a file path");
}
const formData = new FormData();
formData.append("file", fileOrPath);
const res = await fetch("/api/sql-file/preview", { method: "POST", body: formData });
if (!res.ok) throw new Error(await res.text());
return res.json();
}
export async function executeSqlFile(request: SqlFileRequest): Promise<void> {
return post("/api/sql-file/execute", { request });
}
export async function cancelSqlFileExecution(executionId: string): Promise<boolean> {
return post("/api/sql-file/cancel", { executionId });
}
export async function listenSqlFileProgress(_handler: (progress: SqlFileProgress) => void): Promise<() => void> {
// For HTTP mode we need an executionId, but the tauri API does not take one.
// The SSE endpoint requires a specific executionId. As a workaround we return
// a no-op unlisten; callers that need progress in web mode should use
// the web-specific SQL file progress listener instead.
return () => {};
}
export async function pendingOpenSqlFiles(): Promise<string[]> {
return [];
}
export async function pendingOpenConnectionLinks(): Promise<string[]> {
return [];
}
export async function readExternalSqlFile(_path: string): Promise<string> {
throw new Error("Opening external SQL file paths is only available in the desktop app");
}
// ---------------------------------------------------------------------------
// Data Transfer
// ---------------------------------------------------------------------------
export async function startTransfer(
request: TransferRequest,
onProgress: (progress: TransferProgress) => void,
): Promise<void> {
// 1. POST to start the transfer
const res = await fetch("/api/transfer/start", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ request }),
});
if (!res.ok) throw new Error(await res.text());
// 2. SSE to listen for progress
return new Promise((resolve, reject) => {
const es = new EventSource(`/api/transfer/progress/${request.transferId}`);
es.onmessage = (e) => {
const progress: TransferProgress = JSON.parse(e.data);
onProgress(progress);
if (progress.status === "done" || progress.status === "error" || progress.status === "cancelled") {
es.close();
resolve();
}
};
es.onerror = () => {
es.close();
reject(new Error("Transfer SSE connection failed"));
};
});
}
export async function cancelTransfer(transferId: string): Promise<void> {
return post("/api/transfer/cancel", { transferId });
}
// ---------------------------------------------------------------------------
// Table File Import
// ---------------------------------------------------------------------------
export async function previewTableImportFile(fileOrPath: string | File): Promise<TableImportPreview> {
if (typeof fileOrPath === "string") {
throw new Error("previewTableImportFile in web mode requires a File object, not a file path");
}
const formData = new FormData();
formData.append("file", fileOrPath);
const res = await fetch("/api/import/preview", { method: "POST", body: formData });
if (!res.ok) throw new Error(await res.text());
return res.json();
}
export async function importTableFile(
request: TableImportRequest,
onProgress: (progress: TableImportProgress) => void,
): Promise<TableImportSummary> {
// 1. POST to start the import
const res = await fetch("/api/import/execute", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ request }),
});
if (!res.ok) throw new Error(await res.text());
// 2. SSE to listen for progress
return new Promise((resolve, reject) => {
const es = new EventSource(`/api/import/progress/${request.importId}`);
let summary: TableImportSummary | null = null;
es.onmessage = (e) => {
const progress: TableImportProgress = JSON.parse(e.data);
onProgress(progress);
if (progress.status === "done") {
summary = {
importId: progress.importId,
rowsImported: progress.rowsImported,
totalRows: progress.totalRows,
};
es.close();
resolve(summary);
} else if (progress.status === "error" || progress.status === "cancelled") {
es.close();
reject(new Error(progress.error || "Import failed"));
}
};
es.onerror = () => {
es.close();
reject(new Error("Import SSE connection failed"));
};
});
}
export async function cancelTableImport(importId: string): Promise<boolean> {
return post("/api/import/cancel", { importId });
}
// ---------------------------------------------------------------------------
// Database Export
// ---------------------------------------------------------------------------
export async function exportDatabaseSql(
request: DatabaseExportRequest,
onProgress: (progress: ExportProgress) => void,
): Promise<void> {
// 1. POST to start the export
const res = await fetch("/api/export/database", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ request }),
});
if (!res.ok) throw new Error(await res.text());
// 2. SSE to listen for progress
return new Promise((resolve, reject) => {
const es = new EventSource(`/api/export/database/progress/${request.exportId}`);
es.onmessage = (e) => {
const progress: ExportProgress = JSON.parse(e.data);
onProgress(progress);
if (progress.status === "Done" || progress.status === "Error" || progress.status === "Cancelled") {
es.close();
resolve();
}
};
es.onerror = () => {
es.close();
reject(new Error("Export SSE connection failed"));
};
});
}
export async function cancelDatabaseExport(exportId: string): Promise<void> {
await post("/api/export/database/cancel", { exportId });
}
export async function exportQueryResultCsv(
filePath: string,
columns: string[],
rows: readonly (readonly XlsxCellValue[])[],
): Promise<void> {
const { formatCsv } = await import("./exportFormats");
const content = formatCsv(columns, rows as (string | number | boolean | null)[][]);
const fileName = filePath.split(/[\\/]/).pop() || "export.csv";
const blob = new Blob(["\uFEFF", content], { type: "text/csv;charset=utf-8" });
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = fileName;
a.click();
URL.revokeObjectURL(url);
}
function downloadTextFile(filePath: string, fallbackFileName: string, content: string, mimeType: string): void {
const fileName = filePath.split(/[\\/]/).pop() || fallbackFileName;
const blob = new Blob(["\uFEFF", content], { type: mimeType });
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = fileName;
a.click();
URL.revokeObjectURL(url);
}
export async function exportQueryResultXlsx(
filePath: string,
sheetName: string | undefined,
columns: string[],
rows: readonly (readonly XlsxCellValue[])[],
): Promise<void> {
const { buildXlsxWorkbook } = await import("./xlsxExport");
const workbook = buildXlsxWorkbook({
sheetName: sheetName || "Export",
columns,
rows,
});
const fileName = filePath.split(/[\\/]/).pop() || "export.xlsx";
const blob = new Blob([workbook], {
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
});
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = fileName;
a.click();
URL.revokeObjectURL(url);
}
export async function exportQueryResultJson(
filePath: string,
columns: string[],
rows: readonly (readonly XlsxCellValue[])[],
): Promise<void> {
const result = await post<{ content: string }>("/api/export/query-result-json", { columns, rows });
downloadTextFile(filePath, "export.json", result.content, "application/json;charset=utf-8");
}
export async function exportQueryResultMarkdown(
filePath: string,
columns: string[],
rows: readonly (readonly XlsxCellValue[])[],
): Promise<void> {
const result = await post<{ content: string }>("/api/export/query-result-markdown", { columns, rows });
downloadTextFile(filePath, "export.md", result.content, "text/markdown;charset=utf-8");
}
// ---------------------------------------------------------------------------
// Redis
// ---------------------------------------------------------------------------
export async function redisListDatabases(connectionId: string): Promise<RedisDatabaseInfo[]> {
return post("/api/redis/list-databases", { connectionId });
}
export async function redisScanKeys(
connectionId: string,
db: number,
cursor: number,
pattern: string,
count: number,
): Promise<RedisScanResult> {
return post("/api/redis/scan-keys", { connectionId, db, cursor, pattern, count });
}
export async function redisScanValues(
connectionId: string,
db: number,
cursor: number,
pattern: string,
query: string,
count: number,
): Promise<RedisScanResult> {
return post("/api/redis/scan-values", { connectionId, db, cursor, pattern, query, count });
}
export async function redisGetValue(connectionId: string, db: number, keyRaw: string): Promise<RedisValue> {
return post("/api/redis/get-value", { connectionId, db, keyRaw });
}
export async function redisSetString(
connectionId: string,
db: number,
keyRaw: string,
value: string,
ttl?: number,
): Promise<void> {
return post("/api/redis/set-string", { connectionId, db, keyRaw, value, ttl });
}
export async function redisDeleteKey(connectionId: string, db: number, keyRaw: string): Promise<void> {
return post("/api/redis/delete-key", { connectionId, db, keyRaw });
}
export async function redisHashSet(
connectionId: string,
db: number,
keyRaw: string,
field: string,
value: string,
): Promise<void> {
return post("/api/redis/hash-set", { connectionId, db, keyRaw, field, value });
}
export async function redisHashDel(connectionId: string, db: number, keyRaw: string, field: string): Promise<void> {
return post("/api/redis/hash-del", { connectionId, db, keyRaw, field });
}
export async function redisListPush(connectionId: string, db: number, keyRaw: string, value: string): Promise<void> {
return post("/api/redis/list-push", { connectionId, db, keyRaw, value });
}
export async function redisListSet(
connectionId: string,
db: number,
keyRaw: string,
index: number,
value: string,
): Promise<void> {
return post("/api/redis/list-set", { connectionId, db, keyRaw, index, value });
}
export async function redisListRemove(connectionId: string, db: number, keyRaw: string, index: number): Promise<void> {
return post("/api/redis/list-remove", { connectionId, db, keyRaw, index });
}
export async function redisSetAdd(connectionId: string, db: number, keyRaw: string, member: string): Promise<void> {
return post("/api/redis/set-add", { connectionId, db, keyRaw, member });
}
export async function redisSetRemove(connectionId: string, db: number, keyRaw: string, member: string): Promise<void> {
return post("/api/redis/set-remove", { connectionId, db, keyRaw, member });
}
export async function redisZadd(
connectionId: string,
db: number,
keyRaw: string,
member: string,
score: number,
): Promise<void> {
return post("/api/redis/zadd", { connectionId, db, keyRaw, member, score });
}
export async function redisZrem(connectionId: string, db: number, keyRaw: string, member: string): Promise<void> {
return post("/api/redis/zrem", { connectionId, db, keyRaw, member });
}
export async function redisSetTtl(connectionId: string, db: number, keyRaw: string, ttl: number): Promise<void> {
return post("/api/redis/set-ttl", { connectionId, db, keyRaw, ttl });
}
export async function redisDeleteKeys(connectionId: string, db: number, keyRaws: string[]): Promise<number> {
return post("/api/redis/delete-keys", { connectionId, db, keyRaws });
}
export async function redisFlushDb(connectionId: string, db: number): Promise<void> {
return post("/api/redis/flush-db", { connectionId, db });
}
export async function redisExecuteCommand(
connectionId: string,
db: number,
command: string,
): Promise<RedisCommandResult> {
return post("/api/redis/execute-command", { connectionId, db, command });
}
export async function redisLoadMore(
connectionId: string,
db: number,
keyRaw: string,
keyType: string,
cursor: number,
count: number,
): Promise<RedisValue> {
return post("/api/redis/load-more", { connectionId, db, keyRaw, keyType, cursor, count });
}
// ---------------------------------------------------------------------------
// MongoDB
// ---------------------------------------------------------------------------
export async function mongoListDatabases(connectionId: string): Promise<string[]> {
return post("/api/mongo/list-databases", { connectionId });
}
export async function mongoListCollections(connectionId: string, database: string): Promise<string[]> {
return post("/api/mongo/list-collections", { connectionId, database });
}
export async function mongoFindDocuments(
connectionId: string,
database: string,
collection: string,
skip: number,
limit: number,
filter?: string,
sort?: string,
): Promise<MongoDocumentResult> {
return post("/api/mongo/find-documents", { connectionId, database, collection, skip, limit, filter, sort });
}
export async function mongoInsertDocument(
connectionId: string,
database: string,
collection: string,
docJson: string,
): Promise<string> {
return post("/api/mongo/insert-document", { connectionId, database, collection, docJson });
}
export async function mongoUpdateDocument(
connectionId: string,
database: string,
collection: string,
id: string,
docJson: string,
): Promise<number> {
return post("/api/mongo/update-document", { connectionId, database, collection, id, docJson });
}
export async function mongoDeleteDocument(
connectionId: string,
database: string,
collection: string,
id: string,
): Promise<number> {
return post("/api/mongo/delete-document", { connectionId, database, collection, id });
}
// ---------------------------------------------------------------------------
// History
// ---------------------------------------------------------------------------
export async function saveHistory(entry: HistoryEntry): Promise<void> {
return post("/api/history/save", { entry });
}
export async function loadHistory(limit: number, offset: number): Promise<HistoryEntry[]> {
return get(`/api/history?${qs({ limit, offset })}`);
}
export async function clearHistory(): Promise<void> {
return del("/api/history");
}
export async function deleteHistoryEntry(id: string): Promise<void> {
return del(`/api/history/${id}`);
}
// ---------------------------------------------------------------------------
// Updates
// ---------------------------------------------------------------------------
export async function checkForUpdates(): Promise<UpdateInfo> {
return get("/api/update/check");
}
export async function getAppVersion(): Promise<string> {
const res: { version: string } = await get("/api/version");
return res.version;
}
// ---------------------------------------------------------------------------
// Layout
// ---------------------------------------------------------------------------
export async function saveSidebarLayout(layout: SidebarLayout): Promise<void> {
return post("/api/layout/sidebar", { layout });
}
export async function loadSidebarLayout(): Promise<SidebarLayout | null> {
return get("/api/layout/sidebar");
}