Files
dbx/apps/desktop/src/composables/useSchemaOptions.ts
T

81 lines
3.3 KiB
TypeScript

import { ref } from "vue";
import { useConnectionStore } from "@/stores/connectionStore";
import { isSchemaAware as isSchemaAwareType, isSingleDatabase, usesTreeSchemaMode } from "@/lib/database/databaseCapabilities";
import { sortSidebarNames } from "@/lib/database/databaseTree";
import { filterSchemaNamesForConnection } from "@/lib/database/visibleDatabases";
import type { ConnectionConfig } from "@/types/database";
import * as api from "@/lib/backend/api";
export function hasSchemaOptionsCacheEntry(options: Record<string, string[]>, key: string): boolean {
return Object.prototype.hasOwnProperty.call(options, key);
}
export function schemaOptionsCacheKey(connectionId: string, database: string, showSystemSchemas: boolean): string {
return `${connectionId}:${database}:${showSystemSchemas ? "show-system" : "hide-system"}`;
}
export function schemaOptionsForConnection(schemaNames: string[], connection: Pick<ConnectionConfig, "db_type" | "driver_profile" | "visible_databases" | "visible_schemas" | "show_system_schemas"> | undefined, database = ""): string[] {
// Keep numeric schema suffixes in human order (SCHEMA2 before SCHEMA10), matching the database tree.
return sortSidebarNames(filterSchemaNamesForConnection(schemaNames, connection, database));
}
export function useSchemaOptions() {
const connectionStore = useConnectionStore();
const schemaOptions = ref<Record<string, string[]>>({});
const loadingSchemaOptions = ref<Record<string, boolean>>({});
const schemaRequests = new Map<string, Promise<void>>();
function cacheKey(connectionId: string, database: string) {
return schemaOptionsCacheKey(connectionId, database, connectionStore.getConfig(connectionId)?.show_system_schemas === true);
}
function isSchemaAware(connectionId: string): boolean {
return isSchemaAwareType(connectionStore.getConfig(connectionId)?.db_type);
}
async function loadSchemaOptions(connectionId: string, database: string) {
if (!isSchemaAware(connectionId)) return;
const connection = connectionStore.getConfig(connectionId);
const dbType = connection?.db_type;
if (!database && !isSingleDatabase(dbType) && !usesTreeSchemaMode(dbType)) return;
const key = cacheKey(connectionId, database);
if (hasSchemaOptionsCacheEntry(schemaOptions.value, key)) return;
const pending = schemaRequests.get(key);
if (pending) return pending;
const request = (async () => {
loadingSchemaOptions.value[key] = true;
try {
await connectionStore.ensureConnected(connectionId);
schemaOptions.value[key] = schemaOptionsForConnection(await api.listSchemas(connectionId, database), connection, database);
} catch (e) {
schemaOptions.value[key] = [];
throw e;
} finally {
loadingSchemaOptions.value[key] = false;
schemaRequests.delete(key);
}
})();
schemaRequests.set(key, request);
return request;
}
function getSchemaOptionsForDb(connectionId: string, database: string): string[] {
return schemaOptions.value[cacheKey(connectionId, database)] ?? [];
}
function isLoadingSchemas(connectionId: string, database: string): boolean {
return !!loadingSchemaOptions.value[cacheKey(connectionId, database)];
}
return {
schemaOptions,
loadingSchemaOptions,
loadSchemaOptions,
getSchemaOptionsForDb,
isLoadingSchemas,
isSchemaAware,
};
}