feat(xugu): expose programmable object metadata

This commit is contained in:
Elias authored and GitHub committed 2026-07-17 17:53:44 +08:00
1 parent d3887c9936
commit 08cd8903f4
36 files changed
+431 -62

No files matched your search

@@ -154,9 +154,9 @@ watch(deferredSearchQuery, (newQuery, oldQuery) => {
.catch(() => {});
});
const searchableObjectGroupTypes = new Set<TreeNodeType>(["group-tables", "group-views", "group-materialized-views", "group-procedures", "group-functions", "group-sequences", "group-packages"]);
const searchableObjectGroupTypes = new Set<TreeNodeType>(["group-tables", "group-views", "group-materialized-views", "group-procedures", "group-functions", "group-triggers", "group-sequences", "group-packages", "group-types"]);
const simpleObjectParentTypes = new Set<TreeNodeType>(["database", "schema", "linked-server-schema"]);
const simpleObjectChildTypes = new Set<TreeNodeType>(["table", "view", "materialized_view", "procedure", "function", "sequence", "package", "package-body", "load-more"]);
const simpleObjectChildTypes = new Set<TreeNodeType>(["table", "view", "materialized_view", "procedure", "function", "trigger", "sequence", "package", "package-body", "type", "type-body", "load-more"]);
function isSimpleObjectSearchParent(node: TreeNode): boolean {
return settingsStore.editorSettings.sidebarObjectDisplay === "simple" && simpleObjectParentTypes.has(node.type) && node.isExpanded === true && (!!node.children?.some((child) => simpleObjectChildTypes.has(child.type)) || !!store.sidebarTableSearchQueries[node.id]?.trim());
@@ -445,7 +445,22 @@ function hasNodeDatabaseContext(node: TreeNode): node is TreeNode & { connection
return !!node.connectionId && hasTreeNodeDatabaseContext(node);
}
const groupTypes: Set<TreeNodeType> = new Set(["group-columns", "group-indexes", "group-fkeys", "group-triggers", "group-tables", "group-views", "group-materialized-views", "group-procedures", "group-functions", "group-sequences", "group-packages", "group-partitions", "group-extensions"]);
const groupTypes: Set<TreeNodeType> = new Set([
"group-columns",
"group-indexes",
"group-fkeys",
"group-triggers",
"group-tables",
"group-views",
"group-materialized-views",
"group-procedures",
"group-functions",
"group-sequences",
"group-packages",
"group-types",
"group-partitions",
"group-extensions",
]);
function isGroupLabel(node: TreeNode): boolean {
return groupTypes.has(node.type);
@@ -642,7 +657,7 @@ function runRowClickAction(clickDetail: number) {
scheduleOpenData(node);
} else if (isDocumentBrowserTreeNode(node.type)) {
openMongoTreeData(node);
} else if (node.type === "procedure" || node.type === "function" || node.type === "sequence" || node.type === "package" || node.type === "package-body") {
} else if (node.type === "procedure" || node.type === "function" || node.type === "trigger" || node.type === "sequence" || node.type === "package" || node.type === "package-body" || node.type === "type" || node.type === "type-body") {
openObjectSourceDialog(false);
} else if (action === "toggle") {
toggle();
@@ -2833,7 +2848,7 @@ const canOpenFieldLineage = computed(() => {
const hasTypeMenu = computed(() => {
const t = activeNode.value.type;
return t === "connection" || t === "database" || t === "schema" || t === "table" || t === "view" || t === "column" || t === "procedure" || t === "function" || t === "package" || t === "package-body" || isGroupLabel(activeNode.value);
return t === "connection" || t === "database" || t === "schema" || t === "table" || t === "view" || t === "column" || t === "procedure" || t === "function" || t === "trigger" || t === "package" || t === "package-body" || t === "type" || t === "type-body" || isGroupLabel(activeNode.value);
});
const isSelected = computed(() => connectionStore.selectedTreeNodeId === activeNode.value.id);
@@ -3871,7 +3886,7 @@ function buildObjectSidebarMenu(context: SidebarMenuFactoryContext): boolean {
return true;
}
if (node.type === "index" || node.type === "fkey" || node.type === "trigger") {
if (node.type === "index" || node.type === "fkey" || (node.type === "trigger" && !!node.tableName)) {
items.push({ label: t("contextMenu.copyName"), action: copyName, icon: Copy, shortcut: shortcutCopyName.value });
if (node.type === "index" && canOpenStructureEditor.value) {
items.push({ label: "", separator: true });
@@ -3931,7 +3946,7 @@ function buildObjectSidebarMenu(context: SidebarMenuFactoryContext): boolean {
return true;
}
if (node.type === "package" || node.type === "package-body") {
if (node.type === "trigger" || node.type === "package" || node.type === "package-body" || node.type === "type" || node.type === "type-body") {
items.push({ label: t("contextMenu.viewSource"), action: () => openObjectSourceDialog(false), icon: Code2 });
items.push({ label: "", separator: true });
items.push({ label: t("contextMenu.copyName"), action: copyName, icon: Copy, shortcut: shortcutCopyName.value });
@@ -261,6 +261,10 @@ function getIconInfo(node: TreeNode): { icon: any; colorClass: string } | null {
return { icon: Package, colorClass: "text-cyan-500" };
case "package-body":
return { icon: FileCode, colorClass: "text-cyan-400" };
case "type":
return { icon: Braces, colorClass: "text-violet-500" };
case "type-body":
return { icon: FileCode, colorClass: "text-violet-400" };
case "group-tables":
return { icon: Table, colorClass: "text-green-500" };
case "group-views":
@@ -275,6 +279,8 @@ function getIconInfo(node: TreeNode): { icon: any; colorClass: string } | null {
return { icon: ListTree, colorClass: "text-emerald-500" };
case "group-packages":
return { icon: Package, colorClass: "text-cyan-500" };
case "group-types":
return { icon: Braces, colorClass: "text-violet-500" };
case "group-partitions":
return { icon: node.isExpanded ? FolderOpen : FolderClosed, colorClass: "text-green-400" };
case "group-extensions":
@@ -288,7 +294,22 @@ function getIconInfo(node: TreeNode): { icon: any; colorClass: string } | null {
}
}
const groupTypes: Set<TreeNodeType> = new Set(["group-columns", "group-indexes", "group-fkeys", "group-triggers", "group-tables", "group-views", "group-materialized-views", "group-procedures", "group-functions", "group-sequences", "group-packages", "group-partitions", "group-extensions"]);
const groupTypes: Set<TreeNodeType> = new Set([
"group-columns",
"group-indexes",
"group-fkeys",
"group-triggers",
"group-tables",
"group-views",
"group-materialized-views",
"group-procedures",
"group-functions",
"group-sequences",
"group-packages",
"group-types",
"group-partitions",
"group-extensions",
]);
function isGroupLabel(node: TreeNode): boolean {
return groupTypes.has(node.type);
@@ -304,10 +325,11 @@ function displayLabel(node: TreeNode): string {
}
function visibleLabel(node: TreeNode): string {
const withValidity = (label: string) => (node.valid === false ? `${label} · INVALID` : label);
if (node.type === "table" || node.type === "view" || node.type === "materialized_view" || node.type === "mongo-collection" || node.type === "vector-collection" || node.type === "elasticsearch-index") {
return sidebarDisplayTableName(node.label, settingsStore.editorSettings.sidebarHiddenTablePrefixes);
return withValidity(sidebarDisplayTableName(node.label, settingsStore.editorSettings.sidebarHiddenTablePrefixes));
}
return displayLabel(node);
return withValidity(displayLabel(node));
}
type DetailTooltipRow = {