Procházet zdrojové kódy

feat(editor): node.scope (#851)

* feat(editor): node.scope

* fix: variable engine
Yiwei Mao před 3 měsíci
rodič
revize
fcbf83eda4

+ 5 - 6
apps/docs/src/en/guide/advanced/variable/variable-output.mdx

@@ -12,7 +12,7 @@ We mainly divide variables into two categories:
 Outputting a node variable means that this variable is bound to the life cycle of the current node. When the node is created, the variable is born; when the node is deleted, the variable also disappears. We usually have two ways to output node variables:
 
 1.  **Through form configuration**: In the node's setting panel (Form), declare output variables through some preset configurations or custom logic. This method is very intuitive, what you see is what you get.
-2.  **Through API calls**: In the plugin (Plugin), dynamically add, modify or delete variables for the node by calling the `getNodeScope` API. This method is more flexible and suitable for handling complex and dynamic business scenarios.
+2.  **Through API calls**: In the plugin (Plugin), dynamically add, modify or delete variables for the node by calling the `node.scope` API. This method is more flexible and suitable for handling complex and dynamic business scenarios.
 
 Next, we will explore the specific usage of these two methods in depth.
 
@@ -117,13 +117,13 @@ export const nodeRegistries: FlowNodeRegistry[] = [
 
 ```
 
-### Method 2: Use the `getNodeScope` API
+### Method 2: Use the `node.scope` API
 
-In addition to static configuration in the form, we can also get the scope in the plugin (Plugin) through the `getNodeScope` API to dynamically operate the variables of the node.
+In addition to static configuration in the form, we can also get the scope in the plugin (Plugin) through the `node.scope` API to dynamically operate the variables of the node.
 
 This method gives you a high degree of freedom. You can add, delete, modify, and query the variables of the node at any time and any place.
 
-`getNodeScope` will return a node's variable scope (Scope) object, which has several core methods:
+`node.scope` will return a node's variable scope (Scope) object, which has several core methods:
 
 - `setVar(variable)`: Set a variable.
 - `setVar(namespace, variable)`: Set a variable under the specified namespace.
@@ -139,7 +139,6 @@ import {
   FlowDocument,
   definePluginCreator,
   PluginCreator,
-  getNodeScope,
 } from '@flowgram.ai/fixed-layout-editor';
 
 
@@ -147,7 +146,7 @@ export const createSyncVariablePlugin: PluginCreator<SyncVariablePluginOptions>
   definePluginCreator<SyncVariablePluginOptions, FixedLayoutPluginContext>({
     onInit(ctx, options) {
       const startNode = ctx.get(FlowDocument).getNode('start_0');
-      const startScope =  getNodeScope(startNode)
+      const startScope =  startNode.scope!
 
       // 1. Set Variable For Start Scope
       startScope.setVar(

+ 5 - 6
apps/docs/src/zh/guide/advanced/variable/variable-output.mdx

@@ -12,7 +12,7 @@
 输出节点变量,意味着这个变量和当前节点的生命周期是绑定的。当节点被创建时,变量就诞生了;当节点被删除时,变量也随之消逝。我们通常有两种方式来输出节点变量:
 
 1.  **通过表单配置**:在节点的设置面板(Form)中,通过一些预设的配置或自定义的逻辑来声明输出变量。这种方式非常直观,所见即所得。
-2.  **通过 API 调用**:在插件(Plugin)中,通过调用 `getNodeScope` API 来动态地为节点添加、修改或删除变量。这种方式更加灵活,适合处理复杂的、动态的业务场景。
+2.  **通过 API 调用**:在插件(Plugin)中,通过调用 `node.scope` API 来动态地为节点添加、修改或删除变量。这种方式更加灵活,适合处理复杂的、动态的业务场景。
 
 接下来,我们将深入探讨这两种方式的具体用法。
 
@@ -117,13 +117,13 @@ export const nodeRegistries: FlowNodeRegistry[] = [
 
 ```
 
-### 方式二:使用 `getNodeScope` API
+### 方式二:使用 `node.scope` API
 
-除了在表单中静态配置,我们还可以在插件(Plugin)中,通过 `getNodeScope` API 来获取作用域,从而动态地操作节点的变量。
+除了在表单中静态配置,我们还可以在插件(Plugin)中,通过 `node.scope` API 来获取作用域,从而动态地操作节点的变量。
 
 这种方式赋予了你极高的自由度,你可以在任何时机、任何地点,对节点的变量进行增、删、改、查。
 
-`getNodeScope` 会返回一个节点的变量作用域(Scope)对象,这个对象上挂载了几个核心方法:
+`node.scope` 会返回一个节点的变量作用域(Scope)对象,这个对象上挂载了几个核心方法:
 
 - `setVar(variable)`: 设置一个变量。
 - `setVar(namespace, variable)`: 在指定的命名空间下设置一个变量。
@@ -139,7 +139,6 @@ import {
   FlowDocument,
   definePluginCreator,
   PluginCreator,
-  getNodeScope,
 } from '@flowgram.ai/fixed-layout-editor';
 
 
@@ -147,7 +146,7 @@ export const createSyncVariablePlugin: PluginCreator<SyncVariablePluginOptions>
   definePluginCreator<SyncVariablePluginOptions, FixedLayoutPluginContext>({
     onInit(ctx, options) {
       const startNode = ctx.get(FlowDocument).getNode('start_0');
-      const startScope =  getNodeScope(startNode)
+      const startScope =  startNode.scope!
 
       // 1. Set Variable For Start Scope
       startScope.setVar(

+ 28 - 3
packages/client/editor/src/preset/editor-default-preset.ts

@@ -4,6 +4,7 @@
  */
 
 import { interfaces } from 'inversify';
+import { FlowNodeScope, getNodePrivateScope, getNodeScope } from '@flowgram.ai/variable-plugin';
 import { FlowRendererContainerModule, FlowRendererRegistry } from '@flowgram.ai/renderer';
 import { createReduxDevToolPlugin } from '@flowgram.ai/redux-devtool-plugin';
 import { createNodeVariablePlugin } from '@flowgram.ai/node-variable-plugin';
@@ -90,10 +91,11 @@ export function createDefaultPreset<CTX extends EditorPluginContext = EditorPlug
           // }
           // TODO 这个会触发组件注册,后续要废弃这个,通过 materials 插件来做
           ctx.get<FlowRendererRegistry>(FlowRendererRegistry).init();
-          /**
-           * Define node.form
-           */
+
           ctx.document.onNodeCreate(({ node }) => {
+            /**
+             * Define node.form
+             */
             if (opts.nodeEngine && opts.nodeEngine.enable !== false) {
               let cache: NodeFormProps<any> | undefined;
               Object.defineProperty(node, 'form', {
@@ -104,6 +106,29 @@ export function createDefaultPreset<CTX extends EditorPluginContext = EditorPlug
                 },
               });
             }
+
+            /**
+             * Define node.scope & node.privateScope
+             */
+            if (opts.variableEngine && opts.variableEngine.enable !== false) {
+              let cache: FlowNodeScope | undefined;
+              let privateCache: FlowNodeScope | undefined;
+
+              Object.defineProperty(node, 'scope', {
+                get: () => {
+                  if (cache) return cache;
+                  cache = getNodeScope(node);
+                  return cache;
+                },
+              });
+              Object.defineProperty(node, 'privateScope', {
+                get: () => {
+                  if (privateCache) return privateCache;
+                  privateCache = getNodePrivateScope(node);
+                  return privateCache;
+                },
+              });
+            }
           });
         },
         onReady(ctx) {

+ 3 - 1
packages/client/editor/src/preset/editor-props.ts

@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: MIT
  */
 
-import { VariablePluginOptions } from '@flowgram.ai/variable-plugin';
+import { FlowNodeScope, VariablePluginOptions } from '@flowgram.ai/variable-plugin';
 import { ReduxDevToolPluginOptions } from '@flowgram.ai/redux-devtool-plugin';
 import { PlaygroundReactProps, SelectionService } from '@flowgram.ai/playground-react';
 import { NodeCorePluginOptions } from '@flowgram.ai/node-core-plugin';
@@ -25,6 +25,8 @@ import { PluginContext } from '@flowgram.ai/core';
 declare module '@flowgram.ai/document' {
   interface FlowNodeEntity {
     form: NodeFormProps<any> | undefined;
+    scope: FlowNodeScope | undefined;
+    privateScope: FlowNodeScope | undefined;
   }
 }
 

+ 10 - 0
packages/variable-engine/variable-layout/src/utils.ts

@@ -7,10 +7,20 @@ import { FlowNodeEntity } from '@flowgram.ai/document';
 
 import { FlowNodeVariableData } from './flow-node-variable-data';
 
+/**
+ * Use `node.scope` instead
+ * @deprecated
+ * @param node
+ */
 export function getNodeScope(node: FlowNodeEntity) {
   return node.getData(FlowNodeVariableData).public;
 }
 
+/**
+ * Use `node.privateScope` instead
+ * @deprecated
+ * @param node
+ */
 export function getNodePrivateScope(node: FlowNodeEntity) {
   return node.getData(FlowNodeVariableData).initPrivate();
 }