mirror of
https://github.com/basketikun/infinite-canvas.git
synced 2026-08-05 17:04:27 +08:00
feat(plugin): implement canvas node plugin system with dynamic registration and remote installation
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
import { create } from "zustand";
|
||||
|
||||
import type { CanvasNodeDefinition } from "@/types/canvas-plugin";
|
||||
import { CanvasNodeType } from "@/types/canvas";
|
||||
|
||||
const definitions = new Map<string, CanvasNodeDefinition>();
|
||||
const ownerByType = new Map<string, string>(); // type -> pluginId(内置为 "builtin")
|
||||
|
||||
// 注册表版本号,注册/卸载时自增,驱动创建菜单等 UI 重渲染
|
||||
export const useNodeRegistryVersion = create<{ version: number }>(() => ({ version: 0 }));
|
||||
function bump() {
|
||||
useNodeRegistryVersion.setState((state) => ({ version: state.version + 1 }));
|
||||
}
|
||||
|
||||
export function registerNodeDefinitions(defs: CanvasNodeDefinition[], pluginId = "builtin") {
|
||||
defs.forEach((def) => {
|
||||
definitions.set(def.type, def);
|
||||
ownerByType.set(def.type, pluginId);
|
||||
});
|
||||
bump();
|
||||
}
|
||||
|
||||
export function unregisterPluginNodes(pluginId: string) {
|
||||
for (const [type, owner] of ownerByType) {
|
||||
if (owner !== pluginId) continue;
|
||||
definitions.delete(type);
|
||||
ownerByType.delete(type);
|
||||
}
|
||||
bump();
|
||||
}
|
||||
|
||||
export function getNodeDefinition(type: string) {
|
||||
return definitions.get(type);
|
||||
}
|
||||
|
||||
export function getNodePluginId(type: string) {
|
||||
return ownerByType.get(type) || "builtin";
|
||||
}
|
||||
|
||||
export function listNodeDefinitions() {
|
||||
return Array.from(definitions.values());
|
||||
}
|
||||
|
||||
export function isRegisteredNodeType(type: string) {
|
||||
return definitions.has(type);
|
||||
}
|
||||
|
||||
const FALLBACK_SPEC = { width: 340, height: 240, title: "节点", metadata: {} as CanvasNodeDefinition["defaultMetadata"] };
|
||||
|
||||
// 提供默认尺寸/标题/初始 metadata,createCanvasNode 与 agent-ops 复用
|
||||
export function getNodeSpec(type: string) {
|
||||
const def = definitions.get(type);
|
||||
if (!def) return FALLBACK_SPEC;
|
||||
return { width: def.defaultSize.width, height: def.defaultSize.height, title: def.title, metadata: def.defaultMetadata };
|
||||
}
|
||||
|
||||
export function isBuiltinNodeType(type: string) {
|
||||
return (Object.values(CanvasNodeType) as string[]).includes(type);
|
||||
}
|
||||
Reference in New Issue
Block a user