feat(variable): global variable scope (#182)

This commit is contained in:
Yiwei Mao 2025-04-28 10:55:24 +08:00 committed by GitHub
parent 4a6e7a736f
commit 202c06040e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 1325 additions and 39 deletions

View File

@ -3,6 +3,7 @@ import {
FreeLayoutScopeChain, FreeLayoutScopeChain,
FixedLayoutScopeChain, FixedLayoutScopeChain,
VariableLayoutConfig, VariableLayoutConfig,
bindGlobalScope,
} from '@flowgram.ai/variable-layout'; } from '@flowgram.ai/variable-layout';
import { import {
VariableContainerModule, VariableContainerModule,
@ -43,6 +44,8 @@ export const createVariablePlugin = definePluginCreator<VariablePluginOptions>({
if (layoutConfig) { if (layoutConfig) {
bind(VariableLayoutConfig).toConstantValue(layoutConfig || {}); bind(VariableLayoutConfig).toConstantValue(layoutConfig || {});
} }
bindGlobalScope(bind);
}, },
onInit(ctx, opts) { onInit(ctx, opts) {
const { extendASTNodes } = opts || {}; const { extendASTNodes } = opts || {};
@ -55,7 +58,7 @@ export const createVariablePlugin = definePluginCreator<VariablePluginOptions>({
/** /**
* AST * AST
*/ */
(extendASTNodes || []).forEach(info => { (extendASTNodes || []).forEach((info) => {
if (Array.isArray(info)) { if (Array.isArray(info)) {
const [extendASTNode, injector] = info; const [extendASTNode, injector] = info;

View File

@ -1,3 +1,3 @@
export * from './create-variable-plugin'; export * from './create-variable-plugin';
export * from '@flowgram.ai/variable-core'; export * from '@flowgram.ai/variable-core';
export { FlowNodeVariableData } from '@flowgram.ai/variable-layout'; export { FlowNodeVariableData, GlobalScope } from '@flowgram.ai/variable-layout';

View File

@ -5,6 +5,14 @@ import { createMemo } from '../utils/memo';
import { ASTKind, MapNode } from '../ast'; import { ASTKind, MapNode } from '../ast';
import { ScopeAvailableData, ScopeEventData, ScopeOutputData } from './datas'; import { ScopeAvailableData, ScopeEventData, ScopeOutputData } from './datas';
export interface IScopeConstructor {
new (options: {
id: string | symbol;
variableEngine: VariableEngine;
meta?: Record<string, any>;
}): Scope;
}
export class Scope<ScopeMeta extends Record<string, any> = Record<string, any>> { export class Scope<ScopeMeta extends Record<string, any> = Record<string, any>> {
/** /**
* Scope * Scope

View File

@ -7,6 +7,7 @@ import { subsToDisposable } from './utils/toDisposable';
import { createMemo } from './utils/memo'; import { createMemo } from './utils/memo';
import { VariableTable } from './scope/variable-table'; import { VariableTable } from './scope/variable-table';
import { ScopeChangeAction } from './scope/types'; import { ScopeChangeAction } from './scope/types';
import { IScopeConstructor } from './scope/scope';
import { Scope, ScopeChain, type IVariableTable } from './scope'; import { Scope, ScopeChain, type IVariableTable } from './scope';
import { ContainerProvider } from './providers'; import { ContainerProvider } from './providers';
import { ASTRegisters, type GlobalEventActionType } from './ast'; import { ASTRegisters, type GlobalEventActionType } from './ast';
@ -63,12 +64,26 @@ export class VariableEngine implements Disposable {
this.getScopeById(scopeId)?.dispose(); this.getScopeById(scopeId)?.dispose();
} }
// 获取 Scope如果 Scope 存在且类型相同,则会直接使用 /**
createScope(id: string | symbol, meta?: Record<string, any>): Scope { * Get Scope, if Scope exists and type is same, will use it directly
* @param id scope id
* @param meta scope meta, defined by user
* @param ScopeConstructor scope constructor, default is Scope. you can extends Scope to create your own scope
* @returns
*/
createScope(
id: string | symbol,
meta?: Record<string, any>,
options: {
ScopeConstructor?: IScopeConstructor;
} = {}
): Scope {
const { ScopeConstructor = Scope } = options;
let scope = this.getScopeById(id); let scope = this.getScopeById(id);
if (!scope) { if (!scope) {
scope = new Scope({ variableEngine: this, meta, id }); scope = new ScopeConstructor({ variableEngine: this, meta, id });
this.scopeMap.set(id, scope); this.scopeMap.set(id, scope);
this.onScopeChangeEmitter.fire({ type: 'add', scope: scope! }); this.onScopeChangeEmitter.fire({ type: 'add', scope: scope! });

View File

@ -1,5 +1,6 @@
import { Container } from 'inversify'; import { Container } from 'inversify';
import { import {
ASTFactory,
ScopeChain, ScopeChain,
VariableContainerModule, VariableContainerModule,
} from '@flowgram.ai/variable-core'; } from '@flowgram.ai/variable-core';
@ -9,6 +10,8 @@ import {
FixedLayoutScopeChain, FixedLayoutScopeChain,
FlowNodeVariableData, FlowNodeVariableData,
VariableLayoutConfig, VariableLayoutConfig,
GlobalScope,
bindGlobalScope,
} from '../src'; } from '../src';
import { EntityManager } from '@flowgram.ai/core'; import { EntityManager } from '@flowgram.ai/core';
import { VariableEngine } from '@flowgram.ai/variable-core'; import { VariableEngine } from '@flowgram.ai/variable-core';
@ -18,7 +21,13 @@ import {
} from '@flowgram.ai/document'; } from '@flowgram.ai/document';
import { WorkflowDocumentContainerModule, WorkflowLinesManager, WorkflowSimpleLineContribution } from '@flowgram.ai/free-layout-core'; import { WorkflowDocumentContainerModule, WorkflowLinesManager, WorkflowSimpleLineContribution } from '@flowgram.ai/free-layout-core';
export function getContainer(layout: 'free' | 'fixed', layoutConfig?: VariableLayoutConfig): Container { export interface TestConfig extends VariableLayoutConfig {
enableGlobalScope?: boolean;
}
export function getContainer(layout: 'free' | 'fixed', config?: TestConfig): Container {
const { enableGlobalScope, ...layoutConfig } = config || {};
const container = createPlaygroundContainer() as Container; const container = createPlaygroundContainer() as Container;
container.load(VariableContainerModule); container.load(VariableContainerModule);
container.load(FlowDocumentContainerModule); container.load(FlowDocumentContainerModule);
@ -39,10 +48,20 @@ export function getContainer(layout: 'free' | 'fixed', layoutConfig?: VariableLa
container.bind(ScopeChain).to(FixedLayoutScopeChain).inSingletonScope(); container.bind(ScopeChain).to(FixedLayoutScopeChain).inSingletonScope();
} }
bindGlobalScope(container.bind.bind(container))
const entityManager = container.get<EntityManager>(EntityManager); const entityManager = container.get<EntityManager>(EntityManager);
const variableEngine = container.get<VariableEngine>(VariableEngine); const variableEngine = container.get<VariableEngine>(VariableEngine);
const document = container.get<FlowDocument>(FlowDocument); const document = container.get<FlowDocument>(FlowDocument);
if (enableGlobalScope) {
// when get global scope, it will auto create it if not exists
container.get(GlobalScope).setVar(ASTFactory.createVariableDeclaration({
key: 'GlobalScope',
type: ASTFactory.createString(),
}));
}
/** /**
* FlowNodeVariableData * FlowNodeVariableData
*/ */

View File

@ -4,11 +4,10 @@ import { ASTKind } from '@flowgram.ai/variable-core';
import { FlowDocument, FlowDocumentJSON } from '@flowgram.ai/document'; import { FlowDocument, FlowDocumentJSON } from '@flowgram.ai/document';
import { import {
FlowNodeVariableData, FlowNodeVariableData,
VariableLayoutConfig,
} from '../src'; } from '../src';
import { getContainer } from './container' import { TestConfig, getContainer } from './container'
export const runFixedLayoutTest = (testName:string, spec: FlowDocumentJSON, config?: VariableLayoutConfig) => { export const runFixedLayoutTest = (testName:string, spec: FlowDocumentJSON, config?: TestConfig) => {
describe(testName, () => { describe(testName, () => {
const container = getContainer('fixed', config); const container = getContainer('fixed', config);
const flowDocument = container.get(FlowDocument); const flowDocument = container.get(FlowDocument);
@ -27,8 +26,8 @@ export const runFixedLayoutTest = (testName:string, spec: FlowDocumentJSON, conf
} }
}); });
// 创建一个全局作用域 // 创建一个测试作用域
variableEngine.createScope('globalScope'); variableEngine.createScope('testScope');
const traverseVariableDatas = () => const traverseVariableDatas = () =>
flowDocument flowDocument

View File

@ -2,13 +2,12 @@ import { describe, expect, test } from 'vitest';
import { VariableEngine } from '@flowgram.ai/variable-core'; import { VariableEngine } from '@flowgram.ai/variable-core';
import { ASTKind } from '@flowgram.ai/variable-core'; import { ASTKind } from '@flowgram.ai/variable-core';
import { import {
FlowNodeVariableData, FlowNodeVariableData
VariableLayoutConfig,
} from '../src'; } from '../src';
import { getContainer } from './container'; import { TestConfig, getContainer } from './container';
import { WorkflowDocument, WorkflowJSON } from '@flowgram.ai/free-layout-core'; import { WorkflowDocument, WorkflowJSON } from '@flowgram.ai/free-layout-core';
export const runFreeLayoutTest = (testName: string, spec: WorkflowJSON, config?: VariableLayoutConfig) => { export const runFreeLayoutTest = (testName: string, spec: WorkflowJSON, config?: TestConfig) => {
describe(testName, async () => { describe(testName, async () => {
const container = getContainer('free', config); const container = getContainer('free', config);
const flowDocument = container.get(WorkflowDocument); const flowDocument = container.get(WorkflowDocument);
@ -28,7 +27,7 @@ export const runFreeLayoutTest = (testName: string, spec: WorkflowJSON, config?:
}); });
// 创建一个全局作用域 // 创建一个全局作用域
variableEngine.createScope('globalScope'); variableEngine.createScope('testScope');
const traverseVariableDatas = () => const traverseVariableDatas = () =>
flowDocument flowDocument

View File

@ -0,0 +1,781 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`Variable Fix Layout Enable Global Scope > test get Covers 1`] = `
Map {
"start" => [
"getRecords_07e97c55832",
"forEach_260a8f85ff2",
"createRecord_8f85ff2c11d",
"exclusiveSplit_ff2c11d0fb4",
"branch_f2c11d0fb42",
"branch_2c11d0fb42c",
"exclusiveSplit_88dbf2c60ae",
"branch_8dbf2c60aee",
"exclusiveSplit_a59afaadc9a",
"branch_59afaadc9ac",
"branch_9afaadc9acd",
"deleteRecords_c32807e97c5",
"branch_dbf2c60aee4",
"updateRecords_7ed2a172c32",
"end",
],
"getRecords_07e97c55832" => [
"forEach_260a8f85ff2",
"createRecord_8f85ff2c11d",
"exclusiveSplit_ff2c11d0fb4",
"branch_f2c11d0fb42",
"branch_2c11d0fb42c",
"exclusiveSplit_88dbf2c60ae",
"branch_8dbf2c60aee",
"exclusiveSplit_a59afaadc9a",
"branch_59afaadc9ac",
"branch_9afaadc9acd",
"deleteRecords_c32807e97c5",
"branch_dbf2c60aee4",
"updateRecords_7ed2a172c32",
"end",
],
"forEach_260a8f85ff2" => [
"exclusiveSplit_88dbf2c60ae",
"branch_8dbf2c60aee",
"exclusiveSplit_a59afaadc9a",
"branch_59afaadc9ac",
"branch_9afaadc9acd",
"deleteRecords_c32807e97c5",
"branch_dbf2c60aee4",
"updateRecords_7ed2a172c32",
"end",
],
"createRecord_8f85ff2c11d" => [
"exclusiveSplit_ff2c11d0fb4",
"branch_f2c11d0fb42",
"branch_2c11d0fb42c",
],
"exclusiveSplit_ff2c11d0fb4" => [],
"branch_f2c11d0fb42" => [
"branch_2c11d0fb42c",
],
"branch_2c11d0fb42c" => [],
"exclusiveSplit_88dbf2c60ae" => [
"end",
],
"branch_8dbf2c60aee" => [
"branch_dbf2c60aee4",
"updateRecords_7ed2a172c32",
],
"exclusiveSplit_a59afaadc9a" => [],
"branch_59afaadc9ac" => [
"branch_9afaadc9acd",
"deleteRecords_c32807e97c5",
],
"branch_9afaadc9acd" => [],
"deleteRecords_c32807e97c5" => [],
"branch_dbf2c60aee4" => [],
"updateRecords_7ed2a172c32" => [],
"end" => [],
}
`;
exports[`Variable Fix Layout Enable Global Scope > test get Covers After Init Private 1`] = `
Map {
"start" => [
"getRecords_07e97c55832",
"getRecords_07e97c55832_private",
"forEach_260a8f85ff2",
"forEach_260a8f85ff2_private",
"createRecord_8f85ff2c11d",
"createRecord_8f85ff2c11d_private",
"exclusiveSplit_ff2c11d0fb4",
"exclusiveSplit_ff2c11d0fb4_private",
"branch_f2c11d0fb42",
"branch_f2c11d0fb42_private",
"branch_2c11d0fb42c",
"branch_2c11d0fb42c_private",
"exclusiveSplit_88dbf2c60ae",
"exclusiveSplit_88dbf2c60ae_private",
"branch_8dbf2c60aee",
"branch_8dbf2c60aee_private",
"exclusiveSplit_a59afaadc9a",
"exclusiveSplit_a59afaadc9a_private",
"branch_59afaadc9ac",
"branch_59afaadc9ac_private",
"branch_9afaadc9acd",
"branch_9afaadc9acd_private",
"deleteRecords_c32807e97c5",
"deleteRecords_c32807e97c5_private",
"branch_dbf2c60aee4",
"branch_dbf2c60aee4_private",
"updateRecords_7ed2a172c32",
"updateRecords_7ed2a172c32_private",
"end",
"end_private",
],
"getRecords_07e97c55832" => [
"forEach_260a8f85ff2",
"forEach_260a8f85ff2_private",
"createRecord_8f85ff2c11d",
"createRecord_8f85ff2c11d_private",
"exclusiveSplit_ff2c11d0fb4",
"exclusiveSplit_ff2c11d0fb4_private",
"branch_f2c11d0fb42",
"branch_f2c11d0fb42_private",
"branch_2c11d0fb42c",
"branch_2c11d0fb42c_private",
"exclusiveSplit_88dbf2c60ae",
"exclusiveSplit_88dbf2c60ae_private",
"branch_8dbf2c60aee",
"branch_8dbf2c60aee_private",
"exclusiveSplit_a59afaadc9a",
"exclusiveSplit_a59afaadc9a_private",
"branch_59afaadc9ac",
"branch_59afaadc9ac_private",
"branch_9afaadc9acd",
"branch_9afaadc9acd_private",
"deleteRecords_c32807e97c5",
"deleteRecords_c32807e97c5_private",
"branch_dbf2c60aee4",
"branch_dbf2c60aee4_private",
"updateRecords_7ed2a172c32",
"updateRecords_7ed2a172c32_private",
"end",
"end_private",
],
"forEach_260a8f85ff2" => [
"exclusiveSplit_88dbf2c60ae",
"exclusiveSplit_88dbf2c60ae_private",
"branch_8dbf2c60aee",
"branch_8dbf2c60aee_private",
"exclusiveSplit_a59afaadc9a",
"exclusiveSplit_a59afaadc9a_private",
"branch_59afaadc9ac",
"branch_59afaadc9ac_private",
"branch_9afaadc9acd",
"branch_9afaadc9acd_private",
"deleteRecords_c32807e97c5",
"deleteRecords_c32807e97c5_private",
"branch_dbf2c60aee4",
"branch_dbf2c60aee4_private",
"updateRecords_7ed2a172c32",
"updateRecords_7ed2a172c32_private",
"end",
"end_private",
],
"createRecord_8f85ff2c11d" => [
"exclusiveSplit_ff2c11d0fb4",
"exclusiveSplit_ff2c11d0fb4_private",
"branch_f2c11d0fb42",
"branch_f2c11d0fb42_private",
"branch_2c11d0fb42c",
"branch_2c11d0fb42c_private",
],
"exclusiveSplit_ff2c11d0fb4" => [],
"branch_f2c11d0fb42" => [
"branch_2c11d0fb42c",
"branch_2c11d0fb42c_private",
],
"branch_2c11d0fb42c" => [],
"exclusiveSplit_88dbf2c60ae" => [
"end",
"end_private",
],
"branch_8dbf2c60aee" => [
"branch_dbf2c60aee4",
"branch_dbf2c60aee4_private",
"updateRecords_7ed2a172c32",
"updateRecords_7ed2a172c32_private",
],
"exclusiveSplit_a59afaadc9a" => [],
"branch_59afaadc9ac" => [
"branch_9afaadc9acd",
"branch_9afaadc9acd_private",
"deleteRecords_c32807e97c5",
"deleteRecords_c32807e97c5_private",
],
"branch_9afaadc9acd" => [],
"deleteRecords_c32807e97c5" => [],
"branch_dbf2c60aee4" => [],
"updateRecords_7ed2a172c32" => [],
"end" => [],
}
`;
exports[`Variable Fix Layout Enable Global Scope > test get Deps 1`] = `
Map {
"start" => [
"GlobalScope",
],
"getRecords_07e97c55832" => [
"GlobalScope",
"start",
],
"forEach_260a8f85ff2" => [
"GlobalScope",
"start",
"getRecords_07e97c55832",
],
"createRecord_8f85ff2c11d" => [
"GlobalScope",
"start",
"getRecords_07e97c55832",
"forEach_260a8f85ff2",
],
"exclusiveSplit_ff2c11d0fb4" => [
"GlobalScope",
"start",
"getRecords_07e97c55832",
"forEach_260a8f85ff2",
"createRecord_8f85ff2c11d",
],
"branch_f2c11d0fb42" => [
"GlobalScope",
"start",
"getRecords_07e97c55832",
"forEach_260a8f85ff2",
"createRecord_8f85ff2c11d",
"exclusiveSplit_ff2c11d0fb4",
],
"branch_2c11d0fb42c" => [
"GlobalScope",
"start",
"getRecords_07e97c55832",
"forEach_260a8f85ff2",
"createRecord_8f85ff2c11d",
"exclusiveSplit_ff2c11d0fb4",
"branch_f2c11d0fb42",
],
"exclusiveSplit_88dbf2c60ae" => [
"GlobalScope",
"start",
"getRecords_07e97c55832",
"forEach_260a8f85ff2",
],
"branch_8dbf2c60aee" => [
"GlobalScope",
"start",
"getRecords_07e97c55832",
"forEach_260a8f85ff2",
"exclusiveSplit_88dbf2c60ae",
],
"exclusiveSplit_a59afaadc9a" => [
"GlobalScope",
"start",
"getRecords_07e97c55832",
"forEach_260a8f85ff2",
"exclusiveSplit_88dbf2c60ae",
"branch_8dbf2c60aee",
],
"branch_59afaadc9ac" => [
"GlobalScope",
"start",
"getRecords_07e97c55832",
"forEach_260a8f85ff2",
"exclusiveSplit_88dbf2c60ae",
"branch_8dbf2c60aee",
"exclusiveSplit_a59afaadc9a",
],
"branch_9afaadc9acd" => [
"GlobalScope",
"start",
"getRecords_07e97c55832",
"forEach_260a8f85ff2",
"exclusiveSplit_88dbf2c60ae",
"branch_8dbf2c60aee",
"exclusiveSplit_a59afaadc9a",
"branch_59afaadc9ac",
],
"deleteRecords_c32807e97c5" => [
"GlobalScope",
"start",
"getRecords_07e97c55832",
"forEach_260a8f85ff2",
"exclusiveSplit_88dbf2c60ae",
"branch_8dbf2c60aee",
"exclusiveSplit_a59afaadc9a",
"branch_59afaadc9ac",
"branch_9afaadc9acd",
],
"branch_dbf2c60aee4" => [
"GlobalScope",
"start",
"getRecords_07e97c55832",
"forEach_260a8f85ff2",
"exclusiveSplit_88dbf2c60ae",
"branch_8dbf2c60aee",
],
"updateRecords_7ed2a172c32" => [
"GlobalScope",
"start",
"getRecords_07e97c55832",
"forEach_260a8f85ff2",
"exclusiveSplit_88dbf2c60ae",
"branch_8dbf2c60aee",
"branch_dbf2c60aee4",
],
"end" => [
"GlobalScope",
"start",
"getRecords_07e97c55832",
"forEach_260a8f85ff2",
"exclusiveSplit_88dbf2c60ae",
],
}
`;
exports[`Variable Fix Layout Enable Global Scope > test get Deps After Init Private 1`] = `
Map {
"start" => [
"GlobalScope",
"start_private",
],
"getRecords_07e97c55832" => [
"GlobalScope",
"start",
"getRecords_07e97c55832_private",
],
"forEach_260a8f85ff2" => [
"GlobalScope",
"start",
"getRecords_07e97c55832",
"forEach_260a8f85ff2_private",
],
"createRecord_8f85ff2c11d" => [
"GlobalScope",
"start",
"getRecords_07e97c55832",
"forEach_260a8f85ff2",
"forEach_260a8f85ff2_private",
"createRecord_8f85ff2c11d_private",
],
"exclusiveSplit_ff2c11d0fb4" => [
"GlobalScope",
"start",
"getRecords_07e97c55832",
"forEach_260a8f85ff2",
"forEach_260a8f85ff2_private",
"createRecord_8f85ff2c11d",
"exclusiveSplit_ff2c11d0fb4_private",
],
"branch_f2c11d0fb42" => [
"GlobalScope",
"start",
"getRecords_07e97c55832",
"forEach_260a8f85ff2",
"forEach_260a8f85ff2_private",
"createRecord_8f85ff2c11d",
"exclusiveSplit_ff2c11d0fb4",
"exclusiveSplit_ff2c11d0fb4_private",
"branch_f2c11d0fb42_private",
],
"branch_2c11d0fb42c" => [
"GlobalScope",
"start",
"getRecords_07e97c55832",
"forEach_260a8f85ff2",
"forEach_260a8f85ff2_private",
"createRecord_8f85ff2c11d",
"exclusiveSplit_ff2c11d0fb4",
"exclusiveSplit_ff2c11d0fb4_private",
"branch_f2c11d0fb42",
"branch_2c11d0fb42c_private",
],
"exclusiveSplit_88dbf2c60ae" => [
"GlobalScope",
"start",
"getRecords_07e97c55832",
"forEach_260a8f85ff2",
"exclusiveSplit_88dbf2c60ae_private",
],
"branch_8dbf2c60aee" => [
"GlobalScope",
"start",
"getRecords_07e97c55832",
"forEach_260a8f85ff2",
"exclusiveSplit_88dbf2c60ae",
"exclusiveSplit_88dbf2c60ae_private",
"branch_8dbf2c60aee_private",
],
"exclusiveSplit_a59afaadc9a" => [
"GlobalScope",
"start",
"getRecords_07e97c55832",
"forEach_260a8f85ff2",
"exclusiveSplit_88dbf2c60ae",
"exclusiveSplit_88dbf2c60ae_private",
"branch_8dbf2c60aee",
"branch_8dbf2c60aee_private",
"exclusiveSplit_a59afaadc9a_private",
],
"branch_59afaadc9ac" => [
"GlobalScope",
"start",
"getRecords_07e97c55832",
"forEach_260a8f85ff2",
"exclusiveSplit_88dbf2c60ae",
"exclusiveSplit_88dbf2c60ae_private",
"branch_8dbf2c60aee",
"branch_8dbf2c60aee_private",
"exclusiveSplit_a59afaadc9a",
"exclusiveSplit_a59afaadc9a_private",
"branch_59afaadc9ac_private",
],
"branch_9afaadc9acd" => [
"GlobalScope",
"start",
"getRecords_07e97c55832",
"forEach_260a8f85ff2",
"exclusiveSplit_88dbf2c60ae",
"exclusiveSplit_88dbf2c60ae_private",
"branch_8dbf2c60aee",
"branch_8dbf2c60aee_private",
"exclusiveSplit_a59afaadc9a",
"exclusiveSplit_a59afaadc9a_private",
"branch_59afaadc9ac",
"branch_9afaadc9acd_private",
],
"deleteRecords_c32807e97c5" => [
"GlobalScope",
"start",
"getRecords_07e97c55832",
"forEach_260a8f85ff2",
"exclusiveSplit_88dbf2c60ae",
"exclusiveSplit_88dbf2c60ae_private",
"branch_8dbf2c60aee",
"branch_8dbf2c60aee_private",
"exclusiveSplit_a59afaadc9a",
"exclusiveSplit_a59afaadc9a_private",
"branch_59afaadc9ac",
"branch_9afaadc9acd",
"branch_9afaadc9acd_private",
"deleteRecords_c32807e97c5_private",
],
"branch_dbf2c60aee4" => [
"GlobalScope",
"start",
"getRecords_07e97c55832",
"forEach_260a8f85ff2",
"exclusiveSplit_88dbf2c60ae",
"exclusiveSplit_88dbf2c60ae_private",
"branch_8dbf2c60aee",
"branch_dbf2c60aee4_private",
],
"updateRecords_7ed2a172c32" => [
"GlobalScope",
"start",
"getRecords_07e97c55832",
"forEach_260a8f85ff2",
"exclusiveSplit_88dbf2c60ae",
"exclusiveSplit_88dbf2c60ae_private",
"branch_8dbf2c60aee",
"branch_dbf2c60aee4",
"branch_dbf2c60aee4_private",
"updateRecords_7ed2a172c32_private",
],
"end" => [
"GlobalScope",
"start",
"getRecords_07e97c55832",
"forEach_260a8f85ff2",
"exclusiveSplit_88dbf2c60ae",
"end_private",
],
}
`;
exports[`Variable Fix Layout Enable Global Scope > test get private scope Covers 1`] = `
Map {
"start_private" => [
"start",
],
"getRecords_07e97c55832_private" => [
"getRecords_07e97c55832",
],
"forEach_260a8f85ff2_private" => [
"forEach_260a8f85ff2",
"forEach_260a8f85ff2_private",
"createRecord_8f85ff2c11d",
"createRecord_8f85ff2c11d_private",
"exclusiveSplit_ff2c11d0fb4",
"exclusiveSplit_ff2c11d0fb4_private",
"branch_f2c11d0fb42",
"branch_f2c11d0fb42_private",
"branch_2c11d0fb42c",
"branch_2c11d0fb42c_private",
],
"createRecord_8f85ff2c11d_private" => [
"createRecord_8f85ff2c11d",
],
"exclusiveSplit_ff2c11d0fb4_private" => [
"exclusiveSplit_ff2c11d0fb4",
"exclusiveSplit_ff2c11d0fb4_private",
"branch_f2c11d0fb42",
"branch_f2c11d0fb42_private",
"branch_2c11d0fb42c",
"branch_2c11d0fb42c_private",
],
"branch_f2c11d0fb42_private" => [
"branch_f2c11d0fb42",
],
"branch_2c11d0fb42c_private" => [
"branch_2c11d0fb42c",
],
"exclusiveSplit_88dbf2c60ae_private" => [
"exclusiveSplit_88dbf2c60ae",
"exclusiveSplit_88dbf2c60ae_private",
"branch_8dbf2c60aee",
"branch_8dbf2c60aee_private",
"exclusiveSplit_a59afaadc9a",
"exclusiveSplit_a59afaadc9a_private",
"branch_59afaadc9ac",
"branch_59afaadc9ac_private",
"branch_9afaadc9acd",
"branch_9afaadc9acd_private",
"deleteRecords_c32807e97c5",
"deleteRecords_c32807e97c5_private",
"branch_dbf2c60aee4",
"branch_dbf2c60aee4_private",
"updateRecords_7ed2a172c32",
"updateRecords_7ed2a172c32_private",
],
"branch_8dbf2c60aee_private" => [
"branch_8dbf2c60aee",
"branch_8dbf2c60aee_private",
"exclusiveSplit_a59afaadc9a",
"exclusiveSplit_a59afaadc9a_private",
"branch_59afaadc9ac",
"branch_59afaadc9ac_private",
"branch_9afaadc9acd",
"branch_9afaadc9acd_private",
"deleteRecords_c32807e97c5",
"deleteRecords_c32807e97c5_private",
],
"exclusiveSplit_a59afaadc9a_private" => [
"exclusiveSplit_a59afaadc9a",
"exclusiveSplit_a59afaadc9a_private",
"branch_59afaadc9ac",
"branch_59afaadc9ac_private",
"branch_9afaadc9acd",
"branch_9afaadc9acd_private",
"deleteRecords_c32807e97c5",
"deleteRecords_c32807e97c5_private",
],
"branch_59afaadc9ac_private" => [
"branch_59afaadc9ac",
],
"branch_9afaadc9acd_private" => [
"branch_9afaadc9acd",
"branch_9afaadc9acd_private",
"deleteRecords_c32807e97c5",
"deleteRecords_c32807e97c5_private",
],
"deleteRecords_c32807e97c5_private" => [
"deleteRecords_c32807e97c5",
],
"branch_dbf2c60aee4_private" => [
"branch_dbf2c60aee4",
"branch_dbf2c60aee4_private",
"updateRecords_7ed2a172c32",
"updateRecords_7ed2a172c32_private",
],
"updateRecords_7ed2a172c32_private" => [
"updateRecords_7ed2a172c32",
],
"end_private" => [
"end",
],
}
`;
exports[`Variable Fix Layout Enable Global Scope > test get private scope Deps 1`] = `
Map {
"start_private" => [
"GlobalScope",
],
"getRecords_07e97c55832_private" => [
"GlobalScope",
"start",
],
"forEach_260a8f85ff2_private" => [
"GlobalScope",
"start",
"getRecords_07e97c55832",
],
"createRecord_8f85ff2c11d_private" => [
"GlobalScope",
"start",
"getRecords_07e97c55832",
"forEach_260a8f85ff2",
"forEach_260a8f85ff2_private",
],
"exclusiveSplit_ff2c11d0fb4_private" => [
"GlobalScope",
"start",
"getRecords_07e97c55832",
"forEach_260a8f85ff2",
"forEach_260a8f85ff2_private",
"createRecord_8f85ff2c11d",
],
"branch_f2c11d0fb42_private" => [
"GlobalScope",
"start",
"getRecords_07e97c55832",
"forEach_260a8f85ff2",
"forEach_260a8f85ff2_private",
"createRecord_8f85ff2c11d",
"exclusiveSplit_ff2c11d0fb4",
"exclusiveSplit_ff2c11d0fb4_private",
],
"branch_2c11d0fb42c_private" => [
"GlobalScope",
"start",
"getRecords_07e97c55832",
"forEach_260a8f85ff2",
"forEach_260a8f85ff2_private",
"createRecord_8f85ff2c11d",
"exclusiveSplit_ff2c11d0fb4",
"exclusiveSplit_ff2c11d0fb4_private",
"branch_f2c11d0fb42",
],
"exclusiveSplit_88dbf2c60ae_private" => [
"GlobalScope",
"start",
"getRecords_07e97c55832",
"forEach_260a8f85ff2",
],
"branch_8dbf2c60aee_private" => [
"GlobalScope",
"start",
"getRecords_07e97c55832",
"forEach_260a8f85ff2",
"exclusiveSplit_88dbf2c60ae",
"exclusiveSplit_88dbf2c60ae_private",
],
"exclusiveSplit_a59afaadc9a_private" => [
"GlobalScope",
"start",
"getRecords_07e97c55832",
"forEach_260a8f85ff2",
"exclusiveSplit_88dbf2c60ae",
"exclusiveSplit_88dbf2c60ae_private",
"branch_8dbf2c60aee",
"branch_8dbf2c60aee_private",
],
"branch_59afaadc9ac_private" => [
"GlobalScope",
"start",
"getRecords_07e97c55832",
"forEach_260a8f85ff2",
"exclusiveSplit_88dbf2c60ae",
"exclusiveSplit_88dbf2c60ae_private",
"branch_8dbf2c60aee",
"branch_8dbf2c60aee_private",
"exclusiveSplit_a59afaadc9a",
"exclusiveSplit_a59afaadc9a_private",
],
"branch_9afaadc9acd_private" => [
"GlobalScope",
"start",
"getRecords_07e97c55832",
"forEach_260a8f85ff2",
"exclusiveSplit_88dbf2c60ae",
"exclusiveSplit_88dbf2c60ae_private",
"branch_8dbf2c60aee",
"branch_8dbf2c60aee_private",
"exclusiveSplit_a59afaadc9a",
"exclusiveSplit_a59afaadc9a_private",
"branch_59afaadc9ac",
],
"deleteRecords_c32807e97c5_private" => [
"GlobalScope",
"start",
"getRecords_07e97c55832",
"forEach_260a8f85ff2",
"exclusiveSplit_88dbf2c60ae",
"exclusiveSplit_88dbf2c60ae_private",
"branch_8dbf2c60aee",
"branch_8dbf2c60aee_private",
"exclusiveSplit_a59afaadc9a",
"exclusiveSplit_a59afaadc9a_private",
"branch_59afaadc9ac",
"branch_9afaadc9acd",
"branch_9afaadc9acd_private",
],
"branch_dbf2c60aee4_private" => [
"GlobalScope",
"start",
"getRecords_07e97c55832",
"forEach_260a8f85ff2",
"exclusiveSplit_88dbf2c60ae",
"exclusiveSplit_88dbf2c60ae_private",
"branch_8dbf2c60aee",
],
"updateRecords_7ed2a172c32_private" => [
"GlobalScope",
"start",
"getRecords_07e97c55832",
"forEach_260a8f85ff2",
"exclusiveSplit_88dbf2c60ae",
"exclusiveSplit_88dbf2c60ae_private",
"branch_8dbf2c60aee",
"branch_dbf2c60aee4",
"branch_dbf2c60aee4_private",
],
"end_private" => [
"GlobalScope",
"start",
"getRecords_07e97c55832",
"forEach_260a8f85ff2",
"exclusiveSplit_88dbf2c60ae",
],
}
`;
exports[`Variable Fix Layout Enable Global Scope > test sort 1`] = `
[
Symbol(GlobalScope),
"start_private",
"start",
"getRecords_07e97c55832",
"getRecords_07e97c55832_private",
"forEach_260a8f85ff2",
"forEach_260a8f85ff2_private",
"createRecord_8f85ff2c11d",
"createRecord_8f85ff2c11d_private",
"exclusiveSplit_ff2c11d0fb4",
"exclusiveSplit_ff2c11d0fb4_private",
"branch_f2c11d0fb42",
"branch_f2c11d0fb42_private",
"branch_2c11d0fb42c",
"branch_2c11d0fb42c_private",
"exclusiveSplit_88dbf2c60ae",
"exclusiveSplit_88dbf2c60ae_private",
"branch_8dbf2c60aee",
"branch_8dbf2c60aee_private",
"exclusiveSplit_a59afaadc9a",
"exclusiveSplit_a59afaadc9a_private",
"branch_59afaadc9ac",
"branch_59afaadc9ac_private",
"branch_9afaadc9acd",
"branch_9afaadc9acd_private",
"deleteRecords_c32807e97c5",
"deleteRecords_c32807e97c5_private",
"branch_dbf2c60aee4",
"branch_dbf2c60aee4_private",
"updateRecords_7ed2a172c32",
"updateRecords_7ed2a172c32_private",
"end",
"end_private",
"testScope",
"$blockIcon$exclusiveSplit_ff2c11d0fb4",
"$inlineBlocks$exclusiveSplit_ff2c11d0fb4",
"$blockOrderIcon$branch_f2c11d0fb42",
"$blockOrderIcon$branch_2c11d0fb42c",
"$blockIcon$exclusiveSplit_88dbf2c60ae",
"$inlineBlocks$exclusiveSplit_88dbf2c60ae",
"$blockOrderIcon$branch_8dbf2c60aee",
"$blockIcon$exclusiveSplit_a59afaadc9a",
"$inlineBlocks$exclusiveSplit_a59afaadc9a",
"$blockOrderIcon$branch_59afaadc9ac",
"$blockOrderIcon$branch_9afaadc9acd",
"$blockOrderIcon$branch_dbf2c60aee4",
]
`;

View File

@ -630,7 +630,7 @@ exports[`Variable Fix Layout Filter Start End > test sort 1`] = `
"branch_dbf2c60aee4_private", "branch_dbf2c60aee4_private",
"updateRecords_7ed2a172c32", "updateRecords_7ed2a172c32",
"updateRecords_7ed2a172c32_private", "updateRecords_7ed2a172c32_private",
"globalScope", "testScope",
"$blockIcon$exclusiveSplit_ff2c11d0fb4", "$blockIcon$exclusiveSplit_ff2c11d0fb4",
"$inlineBlocks$exclusiveSplit_ff2c11d0fb4", "$inlineBlocks$exclusiveSplit_ff2c11d0fb4",
"$blockOrderIcon$branch_f2c11d0fb42", "$blockOrderIcon$branch_f2c11d0fb42",

View File

@ -128,7 +128,7 @@ exports[`Variable Fix Layout Group > test sort 1`] = `
"node_1_private", "node_1_private",
"end_0", "end_0",
"end_0_private", "end_0_private",
"globalScope", "testScope",
"$group_test$", "$group_test$",
] ]
`; `;

View File

@ -713,7 +713,7 @@ exports[`Variable Fix Layout Without Config > test sort 1`] = `
"updateRecords_7ed2a172c32_private", "updateRecords_7ed2a172c32_private",
"end", "end",
"end_private", "end_private",
"globalScope", "testScope",
"$blockIcon$exclusiveSplit_ff2c11d0fb4", "$blockIcon$exclusiveSplit_ff2c11d0fb4",
"$inlineBlocks$exclusiveSplit_ff2c11d0fb4", "$inlineBlocks$exclusiveSplit_ff2c11d0fb4",
"$blockOrderIcon$branch_f2c11d0fb42", "$blockOrderIcon$branch_f2c11d0fb42",

View File

@ -831,7 +831,7 @@ exports[`Variable Fix Layout > test sort 1`] = `
"updateRecords_7ed2a172c32_private", "updateRecords_7ed2a172c32_private",
"end", "end",
"end_private", "end_private",
"globalScope", "testScope",
"$blockIcon$exclusiveSplit_ff2c11d0fb4", "$blockIcon$exclusiveSplit_ff2c11d0fb4",
"$inlineBlocks$exclusiveSplit_ff2c11d0fb4", "$inlineBlocks$exclusiveSplit_ff2c11d0fb4",
"$blockOrderIcon$branch_f2c11d0fb42", "$blockOrderIcon$branch_f2c11d0fb42",

View File

@ -0,0 +1,343 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`Variable Free Layout Enable Global Scope > test get Covers 1`] = `
Map {
"start_0" => [
"base_1",
"base_2",
"end_0",
"loop_1",
"base_3",
"base_in_loop_1",
"base_in_loop_2",
"base_in_loop_3",
],
"end_0" => [],
"base_1" => [
"base_2",
"end_0",
"loop_1",
"base_3",
"base_in_loop_1",
"base_in_loop_2",
"base_in_loop_3",
],
"base_2" => [
"end_0",
],
"loop_1" => [
"base_3",
"end_0",
],
"base_in_loop_1" => [
"base_in_loop_3",
],
"base_in_loop_2" => [
"base_in_loop_3",
],
"base_in_loop_3" => [],
"base_3" => [
"end_0",
],
}
`;
exports[`Variable Free Layout Enable Global Scope > test get Covers After Init Private 1`] = `
Map {
"start_0" => [
"base_1",
"base_1_private",
"base_2",
"base_2_private",
"end_0",
"end_0_private",
"loop_1",
"loop_1_private",
"base_3",
"base_3_private",
"base_in_loop_1",
"base_in_loop_1_private",
"base_in_loop_2",
"base_in_loop_2_private",
"base_in_loop_3",
"base_in_loop_3_private",
],
"end_0" => [],
"base_1" => [
"base_2",
"base_2_private",
"end_0",
"end_0_private",
"loop_1",
"loop_1_private",
"base_3",
"base_3_private",
"base_in_loop_1",
"base_in_loop_1_private",
"base_in_loop_2",
"base_in_loop_2_private",
"base_in_loop_3",
"base_in_loop_3_private",
],
"base_2" => [
"end_0",
"end_0_private",
],
"loop_1" => [
"base_3",
"base_3_private",
"end_0",
"end_0_private",
],
"base_in_loop_1" => [
"base_in_loop_3",
"base_in_loop_3_private",
],
"base_in_loop_2" => [
"base_in_loop_3",
"base_in_loop_3_private",
],
"base_in_loop_3" => [],
"base_3" => [
"end_0",
"end_0_private",
],
}
`;
exports[`Variable Free Layout Enable Global Scope > test get Deps 1`] = `
Map {
"start_0" => [
"GlobalScope",
],
"end_0" => [
"GlobalScope",
"base_2",
"base_1",
"start_0",
"base_3",
"loop_1",
],
"base_1" => [
"GlobalScope",
"start_0",
],
"base_2" => [
"GlobalScope",
"base_1",
"start_0",
],
"loop_1" => [
"GlobalScope",
"base_1",
"start_0",
],
"base_in_loop_1" => [
"GlobalScope",
"base_1",
"start_0",
],
"base_in_loop_2" => [
"GlobalScope",
"base_1",
"start_0",
],
"base_in_loop_3" => [
"GlobalScope",
"base_in_loop_1",
"base_in_loop_2",
"base_1",
"start_0",
],
"base_3" => [
"GlobalScope",
"loop_1",
"base_1",
"start_0",
],
}
`;
exports[`Variable Free Layout Enable Global Scope > test get Deps After Init Private 1`] = `
Map {
"start_0" => [
"GlobalScope",
"start_0_private",
],
"end_0" => [
"GlobalScope",
"base_2",
"base_1",
"start_0",
"base_3",
"loop_1",
"end_0_private",
],
"base_1" => [
"GlobalScope",
"start_0",
"base_1_private",
],
"base_2" => [
"GlobalScope",
"base_1",
"start_0",
"base_2_private",
],
"loop_1" => [
"GlobalScope",
"base_1",
"start_0",
"loop_1_private",
],
"base_in_loop_1" => [
"GlobalScope",
"base_in_loop_1_private",
"base_1",
"start_0",
"loop_1_private",
],
"base_in_loop_2" => [
"GlobalScope",
"base_in_loop_2_private",
"base_1",
"start_0",
"loop_1_private",
],
"base_in_loop_3" => [
"GlobalScope",
"base_in_loop_1",
"base_in_loop_2",
"base_in_loop_3_private",
"base_1",
"start_0",
"loop_1_private",
],
"base_3" => [
"GlobalScope",
"loop_1",
"base_1",
"start_0",
"base_3_private",
],
}
`;
exports[`Variable Free Layout Enable Global Scope > test get private scope Covers 1`] = `
Map {
"start_0_private" => [
"start_0",
],
"end_0_private" => [
"end_0",
],
"base_1_private" => [
"base_1",
],
"base_2_private" => [
"base_2",
],
"loop_1_private" => [
"base_in_loop_1",
"base_in_loop_1_private",
"base_in_loop_2",
"base_in_loop_2_private",
"base_in_loop_3",
"base_in_loop_3_private",
"loop_1",
],
"base_in_loop_1_private" => [
"base_in_loop_1",
],
"base_in_loop_2_private" => [
"base_in_loop_2",
],
"base_in_loop_3_private" => [
"base_in_loop_3",
],
"base_3_private" => [
"base_3",
],
}
`;
exports[`Variable Free Layout Enable Global Scope > test get private scope Deps 1`] = `
Map {
"start_0_private" => [
"GlobalScope",
],
"end_0_private" => [
"GlobalScope",
"base_2",
"base_1",
"start_0",
"base_3",
"loop_1",
],
"base_1_private" => [
"GlobalScope",
"start_0",
],
"base_2_private" => [
"GlobalScope",
"base_1",
"start_0",
],
"loop_1_private" => [
"GlobalScope",
"base_1",
"start_0",
],
"base_in_loop_1_private" => [
"GlobalScope",
"base_1",
"start_0",
"loop_1_private",
],
"base_in_loop_2_private" => [
"GlobalScope",
"base_1",
"start_0",
"loop_1_private",
],
"base_in_loop_3_private" => [
"GlobalScope",
"base_in_loop_1",
"base_in_loop_2",
"base_1",
"start_0",
"loop_1_private",
],
"base_3_private" => [
"GlobalScope",
"loop_1",
"base_1",
"start_0",
],
}
`;
exports[`Variable Free Layout Enable Global Scope > test sort 1`] = `
[
Symbol(GlobalScope),
"testScope",
"start_0",
"end_0",
"base_1",
"base_2",
"loop_1",
"base_in_loop_1",
"base_in_loop_2",
"base_in_loop_3",
"base_3",
"start_0_private",
"end_0_private",
"base_1_private",
"base_2_private",
"loop_1_private",
"base_in_loop_1_private",
"base_in_loop_2_private",
"base_in_loop_3_private",
"base_3_private",
]
`;

View File

@ -86,7 +86,7 @@ Map {
exports[`Variable Free Layout > test sort 1`] = ` exports[`Variable Free Layout > test sort 1`] = `
[ [
"globalScope", "testScope",
"start_0", "start_0",
"end_0", "end_0",
"base_1", "base_1",

View File

@ -290,7 +290,7 @@ Map {
exports[`Variable Free Layout > test sort 1`] = ` exports[`Variable Free Layout > test sort 1`] = `
[ [
"globalScope", "testScope",
"start_0", "start_0",
"end_0", "end_0",
"base_1", "base_1",

View File

@ -0,0 +1,6 @@
import { runFixedLayoutTest } from '../__mocks__/run-fixed-layout-test';
import { fixLayout1 } from '../__mocks__/fixed-layout-specs';
runFixedLayoutTest('Variable Fix Layout Enable Global Scope', fixLayout1, {
enableGlobalScope: true,
});

View File

@ -0,0 +1,6 @@
import { runFreeLayoutTest } from '../__mocks__/run-free-layout-test';
import { freeLayout1 } from '../__mocks__/free-layout-specs';
runFreeLayoutTest('Variable Free Layout Enable Global Scope', freeLayout1, {
enableGlobalScope: true,
});

View File

@ -3,9 +3,10 @@ import { Scope, ScopeChain } from '@flowgram.ai/variable-core';
import { FlowDocument, type FlowVirtualTree } from '@flowgram.ai/document'; import { FlowDocument, type FlowVirtualTree } from '@flowgram.ai/document';
import { FlowNodeEntity } from '@flowgram.ai/document'; import { FlowNodeEntity } from '@flowgram.ai/document';
import { VariableLayoutConfig } from './variable-layout-config'; import { VariableLayoutConfig } from '../variable-layout-config';
import { FlowNodeScope, FlowNodeScopeTypeEnum, ScopeChainNode } from './types'; import { FlowNodeScope, FlowNodeScopeTypeEnum, ScopeChainNode } from '../types';
import { FlowNodeVariableData } from './flow-node-variable-data'; import { GlobalScope } from '../scopes/global-scope';
import { FlowNodeVariableData } from '../flow-node-variable-data';
/** /**
* FlowVirtualTree ScopeOrder * FlowVirtualTree ScopeOrder
@ -114,6 +115,12 @@ export class FixedLayoutScopeChain extends ScopeChain {
curr = undefined; curr = undefined;
} }
// If scope is GlobalScope, add globalScope to deps
const globalScope = this.variableEngine.getScopeById(GlobalScope.ID);
if (globalScope) {
deps.unshift(globalScope);
}
return this.transformDeps(deps, { scope }); return this.transformDeps(deps, { scope });
} }
@ -123,6 +130,13 @@ export class FixedLayoutScopeChain extends ScopeChain {
return this.transformCovers([], { scope }); return this.transformCovers([], { scope });
} }
// If scope is GlobalScope, return all scopes except GlobalScope
if (GlobalScope.is(scope)) {
return this.variableEngine
.getAllScopes({ sort: true })
.filter((_scope) => !GlobalScope.is(_scope));
}
const node = scope.meta.node; const node = scope.meta.node;
if (!node) { if (!node) {
return this.transformCovers([], { scope }); return this.transformCovers([], { scope });

View File

@ -1,12 +1,13 @@
import { inject, optional, postConstruct } from 'inversify'; import { inject, optional, postConstruct } from 'inversify';
import { Scope, ScopeChain } from '@flowgram.ai/variable-core'; import { Scope, ScopeChain } from '@flowgram.ai/variable-core';
import { WorkflowNodeLinesData, WorkflowNodeMeta } from '@flowgram.ai/free-layout-core';
import { FlowNodeEntity, FlowDocument, FlowVirtualTree } from '@flowgram.ai/document'; import { FlowNodeEntity, FlowDocument, FlowVirtualTree } from '@flowgram.ai/document';
import { EntityManager } from '@flowgram.ai/core'; import { EntityManager } from '@flowgram.ai/core';
import { WorkflowNodeLinesData, WorkflowNodeMeta } from '@flowgram.ai/free-layout-core';
import { VariableLayoutConfig } from './variable-layout-config'; import { VariableLayoutConfig } from '../variable-layout-config';
import { FlowNodeScope, FlowNodeScopeTypeEnum } from './types'; import { FlowNodeScope, FlowNodeScopeTypeEnum } from '../types';
import { FlowNodeVariableData } from './flow-node-variable-data'; import { GlobalScope } from '../scopes/global-scope';
import { FlowNodeVariableData } from '../flow-node-variable-data';
/** /**
* *
@ -44,14 +45,14 @@ export class FreeLayoutScopeChain extends ScopeChain {
// 获取同一层级所有输入节点 // 获取同一层级所有输入节点
protected getAllInputLayerNodes(curr: FlowNodeEntity): FlowNodeEntity[] { protected getAllInputLayerNodes(curr: FlowNodeEntity): FlowNodeEntity[] {
return (curr.getData(WorkflowNodeLinesData)?.allInputNodes || []).filter( return (curr.getData(WorkflowNodeLinesData)?.allInputNodes || []).filter(
_node => _node.parent === curr.parent, (_node) => _node.parent === curr.parent
); );
} }
// 获取同一层级所有输出节点 // 获取同一层级所有输出节点
protected getAllOutputLayerNodes(curr: FlowNodeEntity): FlowNodeEntity[] { protected getAllOutputLayerNodes(curr: FlowNodeEntity): FlowNodeEntity[] {
return (curr.getData(WorkflowNodeLinesData)?.allOutputNodes || []).filter( return (curr.getData(WorkflowNodeLinesData)?.allOutputNodes || []).filter(
_node => _node.parent === curr.parent, (_node) => _node.parent === curr.parent
); );
} }
@ -61,7 +62,7 @@ export class FreeLayoutScopeChain extends ScopeChain {
return this.transformDeps([], { scope }); return this.transformDeps([], { scope });
} }
const scopes: FlowNodeScope[] = []; const deps: FlowNodeScope[] = [];
// 1. 找到依赖的节点 // 1. 找到依赖的节点
let curr: FlowNodeEntity | undefined = node; let curr: FlowNodeEntity | undefined = node;
@ -70,24 +71,37 @@ export class FreeLayoutScopeChain extends ScopeChain {
const allInputNodes: FlowNodeEntity[] = this.getAllInputLayerNodes(curr); const allInputNodes: FlowNodeEntity[] = this.getAllInputLayerNodes(curr);
// 2. 获取所有依赖节点的 public 作用域 // 2. 获取所有依赖节点的 public 作用域
scopes.push( deps.push(
...allInputNodes.map(_node => _node.getData(FlowNodeVariableData).public).filter(Boolean), ...allInputNodes.map((_node) => _node.getData(FlowNodeVariableData).public).filter(Boolean)
); );
// 父节点的 private 也可以访问 // 父节点的 private 也可以访问
const currVarData: FlowNodeVariableData = curr.getData(FlowNodeVariableData); const currVarData: FlowNodeVariableData = curr.getData(FlowNodeVariableData);
if (currVarData?.private && scope !== currVarData.private) { if (currVarData?.private && scope !== currVarData.private) {
scopes.push(currVarData.private); deps.push(currVarData.private);
} }
curr = this.getParent(curr); curr = this.getParent(curr);
} }
const uniqScopes = Array.from(new Set(scopes)); // If scope is GlobalScope, add globalScope to deps
return this.transformDeps(uniqScopes, { scope }); const globalScope = this.variableEngine.getScopeById(GlobalScope.ID);
if (globalScope) {
deps.unshift(globalScope);
}
const uniqDeps = Array.from(new Set(deps));
return this.transformDeps(uniqDeps, { scope });
} }
getCovers(scope: FlowNodeScope): FlowNodeScope[] { getCovers(scope: FlowNodeScope): FlowNodeScope[] {
// If scope is GlobalScope, return all scopes except GlobalScope
if (GlobalScope.is(scope)) {
return this.variableEngine
.getAllScopes({ sort: true })
.filter((_scope) => !GlobalScope.is(_scope));
}
const { node } = scope.meta || {}; const { node } = scope.meta || {};
if (!node) { if (!node) {
return this.transformCovers([], { scope }); return this.transformCovers([], { scope });

View File

@ -1,9 +1,10 @@
export { FlowNodeVariableData } from './flow-node-variable-data'; export { FlowNodeVariableData } from './flow-node-variable-data';
export { FreeLayoutScopeChain } from './free-layout-scope-chain'; export { FreeLayoutScopeChain } from './chains/free-layout-scope-chain';
export { VariableLayoutConfig } from './variable-layout-config'; export { VariableLayoutConfig } from './variable-layout-config';
export { FixedLayoutScopeChain } from './fixed-layout-scope-chain'; export { FixedLayoutScopeChain } from './chains/fixed-layout-scope-chain';
export { export {
type FlowNodeScopeMeta, type FlowNodeScopeMeta,
type FlowNodeScope, type FlowNodeScope,
FlowNodeScopeTypeEnum as FlowNodeScopeType, FlowNodeScopeTypeEnum as FlowNodeScopeType,
} from './types'; } from './types';
export { GlobalScope, bindGlobalScope } from './scopes/global-scope';

View File

@ -0,0 +1,78 @@
import { injectable, interfaces } from 'inversify';
import { ASTNode, ASTNodeJSON, Scope, VariableEngine } from '@flowgram.ai/variable-core';
@injectable()
export class GlobalScope extends Scope {
static readonly ID = Symbol('GlobalScope');
static is(scope: Scope): scope is GlobalScope {
return scope.id === GlobalScope.ID;
}
/**
* Sets a variable in the Global Scope with the given key and JSON value.
*
* @param key - The key under which the variable will be stored.
* @param json - The JSON value to store.
* @returns The updated AST node.
*/
public setVar(key: string, json: ASTNodeJSON): ASTNode;
/**
* Sets a variable in the Global Scope with the default key 'outputs'.
*
* @param json - The JSON value to store.
* @returns The updated AST node.
*/
public setVar(json: ASTNodeJSON): ASTNode;
public setVar(arg1: string | ASTNodeJSON, arg2?: ASTNodeJSON): ASTNode {
if (typeof arg1 === 'string' && arg2 !== undefined) {
return this.ast.set(arg1, arg2);
}
if (typeof arg1 === 'object' && arg2 === undefined) {
return this.ast.set('outputs', arg1);
}
throw new Error('Invalid arguments');
}
/**
* Retrieves a variable from the Global Scope by key.
*
* @param key - The key of the variable to retrieve. Defaults to 'outputs'.
* @returns The value of the variable, or undefined if not found.
*/
public getVar(key: string = 'outputs') {
return this.ast.get(key);
}
/**
* Clears a variable from the Global Scope by key.
*
* @param key - The key of the variable to clear. Defaults to 'outputs'.
* @returns The updated AST node.
*/
public clearVar(key: string = 'outputs') {
return this.ast.remove(key);
}
}
export const bindGlobalScope = (bind: interfaces.Bind) => {
bind(GlobalScope).toDynamicValue((ctx) => {
const variableEngine = ctx.container.get(VariableEngine);
let scope = variableEngine.getScopeById(GlobalScope.ID) as GlobalScope;
if (!scope) {
scope = variableEngine.createScope(
GlobalScope.ID,
{},
{ ScopeConstructor: GlobalScope }
) as GlobalScope;
variableEngine.chain.refreshAllChange();
}
return scope;
});
};