Przeglądaj źródła

fix(core): deduplication before singleton plugin init (#142)

Louis Young 9 miesięcy temu
rodzic
commit
f43d70ee88

+ 26 - 14
packages/canvas-engine/core/src/plugin/plugin.ts

@@ -65,6 +65,7 @@ export const Plugin = Symbol('Plugin');
 export type Plugin<Options = any> = {
   options: Options;
   pluginId: string;
+  singleton: boolean;
   initPlugin: () => void;
   contributionKeys?: interfaces.ServiceIdentifier[];
   containerModules?: interfaces.ContainerModule[];
@@ -78,22 +79,31 @@ export type PluginCreator<Options> = (opts: Options) => Plugin<Options>;
 
 export function loadPlugins(plugins: Plugin[], container: interfaces.Container): void {
   const pluginInitSet = new Set<string>();
-  const modules: interfaces.ContainerModule[] = plugins.reduce((res, plugin) => {
-    if (!pluginInitSet.has(plugin.pluginId)) {
-      plugin.initPlugin();
-      pluginInitSet.add(plugin.pluginId);
-    }
-    if (plugin.containerModules && plugin.containerModules.length > 0) {
-      for (let module of plugin.containerModules) {
-        // 去重
-        if (!res.includes(module)) {
-          res.push(module);
+  const singletonPluginIds = new Set<string>();
+  const modules: interfaces.ContainerModule[] = plugins
+    .reduceRight((result: Plugin[], plugin: Plugin) => {
+      const shouldSkip = plugin.singleton && singletonPluginIds.has(plugin.pluginId);
+      if (plugin.singleton) {
+        singletonPluginIds.add(plugin.pluginId);
+      }
+      return shouldSkip ? result : [plugin, ...result];
+    }, [])
+    .reduce((res, plugin) => {
+      if (!pluginInitSet.has(plugin.pluginId)) {
+        plugin.initPlugin();
+        pluginInitSet.add(plugin.pluginId);
+      }
+      if (plugin.containerModules && plugin.containerModules.length > 0) {
+        for (let module of plugin.containerModules) {
+          // 去重
+          if (!res.includes(module)) {
+            res.push(module);
+          }
         }
+        return res;
       }
       return res;
-    }
-    return res;
-  }, [] as interfaces.ContainerModule[]);
+    }, [] as interfaces.ContainerModule[]);
   modules.forEach((module) => container.load(module));
   plugins.forEach((plugin) => {
     if (plugin.contributionKeys) {
@@ -139,9 +149,10 @@ export function definePluginCreator<Options, CTX extends PluginContext = PluginC
   config: {
     containerModules?: interfaces.ContainerModule[];
     contributionKeys?: interfaces.ServiceIdentifier[];
+    singleton?: boolean;
   } & PluginConfig<Options, CTX>
 ): PluginCreator<Options> {
-  const { contributionKeys } = config;
+  const { contributionKeys, singleton = false } = config;
   pluginIndex += 1;
   const pluginId = `Playground_${pluginIndex}`;
   return (opts: Options) => {
@@ -150,6 +161,7 @@ export function definePluginCreator<Options, CTX extends PluginContext = PluginC
 
     return {
       pluginId,
+      singleton,
       initPlugin: () => {
         // 防止 plugin 被上层业务多次 init
         if (isInit) {

+ 1 - 0
packages/plugins/free-lines-plugin/src/create-free-lines-plugin.ts

@@ -6,6 +6,7 @@ import { WorkflowLinesLayer } from './layer';
 import { WorkflowBezierLineContribution, WorkflowFoldLineContribution } from './contributions';
 
 export const createFreeLinesPlugin = definePluginCreator({
+  singleton: true,
   onInit: (ctx: PluginContext, opts: FreeLinesPluginOptions) => {
     ctx.playground.registerLayer(WorkflowLinesLayer, {
       ...opts,