fix(kingbase): compat V8 routine source and add extension details

This commit is contained in:
zipg authored and GitHub committed 2026-08-08 10:38:16 +08:00
1 parent 1405f00060
commit fa2365153a
18 files changed
+315 -6

No files matched your search

@@ -0,0 +1,67 @@
<script setup lang="ts">
import { computed, ref } from "vue";
import { Package } from "@lucide/vue";
import { useI18n } from "vue-i18n";
import { Button } from "@/components/ui/button";
import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog";
import type { ExtensionInfo, TreeNode } from "@/types/database";
const { t } = useI18n();
const props = defineProps<{
node: TreeNode;
}>();
const open = ref(false);
const extension = computed<ExtensionInfo>(() => {
const meta = props.node.meta as ExtensionInfo | undefined;
return {
name: meta?.name || props.node.label,
version: meta?.version || "-",
schema: meta?.schema || props.node.schema || null,
comment: meta?.comment || null,
};
});
function show() {
open.value = true;
}
defineExpose({ show });
</script>
<template>
<Dialog v-model:open="open">
<DialogContent class="sm:max-w-lg">
<DialogHeader>
<DialogTitle class="flex min-w-0 items-center gap-2 pr-8">
<Package class="h-4 w-4 shrink-0 text-violet-500" />
<span class="truncate">{{ t("extension.detailsTitle") }}</span>
</DialogTitle>
</DialogHeader>
<dl class="overflow-hidden rounded-md border text-sm">
<div class="grid grid-cols-[7rem_minmax(0,1fr)] border-b px-3 py-2.5">
<dt class="text-muted-foreground">{{ t("extension.name") }}</dt>
<dd class="min-w-0 break-words font-medium">{{ extension.name }}</dd>
</div>
<div class="grid grid-cols-[7rem_minmax(0,1fr)] border-b px-3 py-2.5">
<dt class="text-muted-foreground">{{ t("connection.version") }}</dt>
<dd class="min-w-0 break-words">{{ extension.version }}</dd>
</div>
<div class="grid grid-cols-[7rem_minmax(0,1fr)] border-b px-3 py-2.5">
<dt class="text-muted-foreground">Schema</dt>
<dd class="min-w-0 break-words">{{ extension.schema || "-" }}</dd>
</div>
<div class="grid grid-cols-[7rem_minmax(0,1fr)] px-3 py-2.5">
<dt class="text-muted-foreground">{{ t("structureEditor.comment") }}</dt>
<dd class="min-w-0 whitespace-pre-wrap break-words">{{ extension.comment || "-" }}</dd>
</div>
</dl>
<DialogFooter>
<Button variant="outline" @click="open = false">{{ t("common.close") }}</Button>
</DialogFooter>
</DialogContent>
</Dialog>
</template>
@@ -0,0 +1,80 @@
// @vitest-environment happy-dom
import { createApp, defineComponent, h, nextTick, ref, type App } from "vue";
import { afterEach, describe, expect, it, vi } from "vitest";
import i18n from "@/i18n";
import type { TreeNode } from "@/types/database";
vi.mock("@/components/ui/dialog", async () => {
const { defineComponent, h } = await import("vue");
const passthrough = defineComponent({
setup(_props, { slots }) {
return () => h("div", slots.default?.());
},
});
const dialog = defineComponent({
props: { open: Boolean },
setup(props, { slots }) {
return () => (props.open ? h("div", slots.default?.()) : null);
},
});
return { Dialog: dialog, DialogContent: passthrough, DialogFooter: passthrough, DialogHeader: passthrough, DialogTitle: passthrough };
});
vi.mock("@/components/ui/button", async () => {
const { defineComponent, h } = await import("vue");
return {
Button: defineComponent({
setup(_props, { slots }) {
return () => h("button", slots.default?.());
},
}),
};
});
import ExtensionDetailsDialog from "@/components/objects/ExtensionDetailsDialog.vue";
const mountedApps: App[] = [];
afterEach(() => {
for (const app of mountedApps.splice(0)) app.unmount();
document.body.innerHTML = "";
});
describe("ExtensionDetailsDialog", () => {
it("shows metadata already loaded for the extension tree node", async () => {
const node: TreeNode = {
id: "connection:database:public:sys_stat_statements",
label: "sys_stat_statements",
type: "extension",
schema: "public",
meta: {
name: "sys_stat_statements",
version: "1.10",
schema: "public",
comment: "track planning and execution statistics",
},
};
const dialog = ref<InstanceType<typeof ExtensionDetailsDialog> | null>(null);
const container = document.createElement("div");
document.body.append(container);
const app = createApp(
defineComponent({
setup() {
return () => h(ExtensionDetailsDialog, { ref: dialog, node });
},
}),
);
mountedApps.push(app);
app.use(i18n);
app.mount(container);
dialog.value?.show();
await nextTick();
const text = document.body.textContent || "";
expect(text).toContain("sys_stat_statements");
expect(text).toContain("1.10");
expect(text).toContain("public");
expect(text).toContain("track planning and execution statistics");
});
});