chore(demo): remove sync-variable-plugin in demo-nextjs-antd (#442)

This commit is contained in:
Yiwei Mao 2025-07-02 15:10:44 +08:00 committed by GitHub
parent d8e2b4a838
commit 522bc0770d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 211 additions and 100 deletions

View File

@ -18,7 +18,7 @@ import { createContainerNodePlugin } from '@flowgram.ai/free-container-plugin';
import { onDragLineEnd } from '@editor/utils'; import { onDragLineEnd } from '@editor/utils';
import { FlowNodeRegistry } from '@editor/typings'; import { FlowNodeRegistry } from '@editor/typings';
import { createContextMenuPlugin, createSyncVariablePlugin } from '@editor/plugins'; import { createContextMenuPlugin } from '@editor/plugins';
import { defaultFormMeta } from '@editor/nodes/default-form-meta'; import { defaultFormMeta } from '@editor/nodes/default-form-meta';
import { WorkflowNodeType } from '@editor/nodes'; import { WorkflowNodeType } from '@editor/nodes';
import { BaseNode } from '@editor/components/base-node'; import { BaseNode } from '@editor/components/base-node';
@ -156,11 +156,6 @@ export const useEditorProps = (initialData: WorkflowJSON, nodeRegistries: FlowNo
}, },
inactiveDebounceTime: 1, inactiveDebounceTime: 1,
}), }),
/**
* Variable plugin
*
*/
createSyncVariablePlugin({}),
/** /**
* Snap plugin * Snap plugin
* 线 * 线

View File

@ -4,7 +4,7 @@
*/ */
import { FormMeta, FormRenderProps, ValidateTrigger } from '@flowgram.ai/free-layout-editor'; import { FormMeta, FormRenderProps, ValidateTrigger } from '@flowgram.ai/free-layout-editor';
import { autoRenameRefEffect } from '@flowgram.ai/form-antd-materials'; import { autoRenameRefEffect, syncVariableTitle, provideJsonSchemaOutputs } from '@flowgram.ai/form-antd-materials';
import { FormContent, FormHeader, FormInputs, FormOutputs } from '@editor/form-components'; import { FormContent, FormHeader, FormInputs, FormOutputs } from '@editor/form-components';
import { FlowNodeJSON } from '../typings'; import { FlowNodeJSON } from '../typings';
@ -36,7 +36,9 @@ export const defaultFormMeta: FormMeta<FlowNodeJSON> = {
return undefined; return undefined;
}, },
}, },
effect: { effect: {
title: syncVariableTitle,
outputs: provideJsonSchemaOutputs,
inputsValues: autoRenameRefEffect, inputsValues: autoRenameRefEffect,
}, },
}; };

View File

@ -12,7 +12,7 @@ import {
FormRenderProps, FormRenderProps,
ValidateTrigger, ValidateTrigger,
} from '@flowgram.ai/free-layout-editor'; } from '@flowgram.ai/free-layout-editor';
import { JsonSchemaEditor } from '@flowgram.ai/form-antd-materials'; import { JsonSchemaEditor, syncVariableTitle, provideJsonSchemaOutputs } from '@flowgram.ai/form-antd-materials';
import { FlowNodeJSON, JsonSchema } from '@editor/typings'; import { FlowNodeJSON, JsonSchema } from '@editor/typings';
import { useIsSidebar } from '@editor/hooks'; import { useIsSidebar } from '@editor/hooks';
@ -57,4 +57,8 @@ export const formMeta: FormMeta<FlowNodeJSON> = {
validate: { validate: {
title: ({ value }: { value: string }) => (value ? undefined : 'Title is required'), title: ({ value }: { value: string }) => (value ? undefined : 'Title is required'),
}, },
effect: {
title: syncVariableTitle,
outputs: provideJsonSchemaOutputs,
},
}; };

View File

@ -3,5 +3,4 @@
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
*/ */
export { createSyncVariablePlugin } from './sync-variable-plugin/sync-variable-plugin';
export { createContextMenuPlugin } from './context-menu-plugin'; export { createContextMenuPlugin } from './context-menu-plugin';

View File

@ -1,85 +0,0 @@
/**
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
* SPDX-License-Identifier: MIT
*/
'use client';
import {
ASTFactory,
FlowNodeVariableData,
FreeLayoutPluginContext,
PluginCreator,
definePluginCreator,
getNodeForm,
} from '@flowgram.ai/free-layout-editor';
import { JsonSchemaUtils } from '@flowgram.ai/form-antd-materials';
export interface SyncVariablePluginOptions {}
/**
* Creates a plugin to synchronize output data to the variable engine when nodes are created or updated.
* @param ctx - The plugin context, containing the document and other relevant information.
* @param options - Plugin options, currently an empty object.
*/
export const createSyncVariablePlugin: PluginCreator<SyncVariablePluginOptions> =
definePluginCreator<SyncVariablePluginOptions, FreeLayoutPluginContext>({
onInit(ctx, options) {
const flowDocument = ctx.document;
// Listen for node creation events
flowDocument.onNodeCreate(({ node }) => {
const form = getNodeForm(node);
const variableData = node.getData(FlowNodeVariableData);
/**
* Synchronizes output data to the variable engine.
* @param value - The output data to synchronize.
*/
const syncOutputs = (value: any) => {
if (!value) {
// If the output data is empty, clear the variable
variableData?.clearVar();
return;
}
// Create an Type AST from the output data's JSON schema
// NOTICE: You can create a new function to generate an AST based on YOUR CUSTOM DSL
const typeAST = JsonSchemaUtils.schemaToAST(value);
if (typeAST) {
// Use the node's title or its ID as the title for the variable
const title = form?.getValueIn('title') || node.id;
// Set the variable in the variable engine
variableData?.setVar(
ASTFactory.createVariableDeclaration({
meta: {
title: `${title}`,
icon: node.getNodeRegistry()?.info?.icon,
// NOTICE: You can add more metadata here as needed
},
key: `${node.id}`,
type: typeAST,
})
);
} else {
// If the AST cannot be created, clear the variable
variableData?.clearVar();
}
};
if (form) {
// Initially synchronize the output data
syncOutputs(form.getValueIn('outputs'));
// Listen for changes in the form values and re-synchronize when outputs change
form.onFormValuesChange((props) => {
if (props.name.match(/^outputs/) || props.name.match(/^title/)) {
syncOutputs(form.getValueIn('outputs'));
}
});
}
});
},
});

View File

@ -6,3 +6,5 @@
export * from './provide-batch-input'; export * from './provide-batch-input';
export * from './provide-batch-outputs'; export * from './provide-batch-outputs';
export * from './auto-rename-ref'; export * from './auto-rename-ref';
export * from './provide-json-schema-outputs';
export * from './sync-variable-title';

View File

@ -14,7 +14,6 @@ import {
import { IFlowRefValue } from '../../typings'; import { IFlowRefValue } from '../../typings';
export const provideBatchOutputsEffect: EffectOptions[] = createEffectFromVariableProvider({ export const provideBatchOutputsEffect: EffectOptions[] = createEffectFromVariableProvider({
private: true,
parse: (value: Record<string, IFlowRefValue>, ctx) => [ parse: (value: Record<string, IFlowRefValue>, ctx) => [
ASTFactory.createVariableDeclaration({ ASTFactory.createVariableDeclaration({
key: `${ctx.node.id}`, key: `${ctx.node.id}`,

View File

@ -0,0 +1,8 @@
{
"name": "provide-json-schema-outputs",
"depMaterials": [
"typings/json-schema",
"utils/json-schema"
],
"depPackages": []
}

View File

@ -0,0 +1,28 @@
/**
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
* SPDX-License-Identifier: MIT
*/
import {
ASTFactory,
EffectOptions,
FlowNodeRegistry,
createEffectFromVariableProvider,
getNodeForm,
} from '@flowgram.ai/editor';
import { JsonSchemaUtils } from '../../utils';
import { IJsonSchema } from '../../typings';
export const provideJsonSchemaOutputs: EffectOptions[] = createEffectFromVariableProvider({
parse: (value: IJsonSchema, ctx) => [
ASTFactory.createVariableDeclaration({
key: `${ctx.node.id}`,
meta: {
title: getNodeForm(ctx.node)?.getValueIn('title') || ctx.node.id,
icon: ctx.node.getNodeRegistry<FlowNodeRegistry>().info?.icon,
},
type: JsonSchemaUtils.schemaToAST(value),
}),
],
});

View File

@ -0,0 +1,5 @@
{
"name": "sync-variable-title",
"depMaterials": [],
"depPackages": []
}

View File

@ -0,0 +1,28 @@
/**
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
* SPDX-License-Identifier: MIT
*/
import {
DataEvent,
Effect,
EffectOptions,
FlowNodeRegistry,
FlowNodeVariableData,
} from '@flowgram.ai/editor';
export const syncVariableTitle: EffectOptions[] = [
{
event: DataEvent.onValueChange,
effect: (({ value, context }) => {
context.node.getData(FlowNodeVariableData).allScopes.forEach((_scope) => {
_scope.output.variables.forEach((_var) => {
_var.updateMeta({
title: value || context.node.id,
icon: context.node.getNodeRegistry<FlowNodeRegistry>().info?.icon,
});
});
});
}) as Effect,
},
];

View File

@ -0,0 +1,7 @@
{
"name": "batch-outputs-plugin",
"depMaterials": [
"flow-value"
],
"depPackages": []
}

View File

@ -0,0 +1,104 @@
/**
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
* SPDX-License-Identifier: MIT
*/
import {
ASTFactory,
createEffectFromVariableProvider,
defineFormPluginCreator,
FlowNodeRegistry,
getNodeForm,
getNodePrivateScope,
getNodeScope,
ScopeChainTransformService,
type EffectOptions,
type FormPluginCreator,
FlowNodeScopeType,
} from '@flowgram.ai/editor';
import { IFlowRefValue } from '../../typings';
export const provideBatchOutputsEffect: EffectOptions[] = createEffectFromVariableProvider({
parse: (value: Record<string, IFlowRefValue>, ctx) => [
ASTFactory.createVariableDeclaration({
key: `${ctx.node.id}`,
meta: {
title: getNodeForm(ctx.node)?.getValueIn('title'),
icon: ctx.node.getNodeRegistry<FlowNodeRegistry>().info?.icon,
},
type: ASTFactory.createObject({
properties: Object.entries(value).map(([_key, value]) =>
ASTFactory.createProperty({
key: _key,
initializer: ASTFactory.createWrapArrayExpression({
wrapFor: ASTFactory.createKeyPathExpression({
keyPath: value?.content || [],
}),
}),
})
),
}),
}),
],
});
/**
* Free Layout only right now
*/
export const createBatchOutputsFormPlugin: FormPluginCreator<{ outputKey: string }> =
defineFormPluginCreator({
name: 'batch-outputs-plugin',
onSetupFormMeta({ mergeEffect }, { outputKey }) {
mergeEffect({
[outputKey]: provideBatchOutputsEffect,
});
},
onInit(ctx, { outputKey }) {
const chainTransformService = ctx.node.getService(ScopeChainTransformService);
const batchNodeType = ctx.node.flowNodeType;
const transformerId = `${batchNodeType}-outputs`;
if (chainTransformService.hasTransformer(transformerId)) {
return;
}
chainTransformService.registerTransformer(transformerId, {
transformCovers: (covers, ctx) => {
const node = ctx.scope.meta?.node;
// Child Node's variable can cover parent
if (node?.parent?.flowNodeType === batchNodeType) {
return [...covers, getNodeScope(node.parent)];
}
return covers;
},
transformDeps(scopes, ctx) {
const scopeMeta = ctx.scope.meta;
if (scopeMeta?.type === FlowNodeScopeType.private) {
return scopes;
}
const node = scopeMeta?.node;
// Public of Loop Node depends on child Node
if (node?.flowNodeType === batchNodeType) {
// Get all child blocks
const childBlocks = node.blocks;
// public scope of all child blocks
return [
getNodePrivateScope(node),
...childBlocks.map((_childBlock) => getNodeScope(_childBlock)),
];
}
return scopes;
},
});
},
});

View File

@ -3,4 +3,4 @@
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
*/ */
export * from './sync-variable-plugin'; export { createBatchOutputsFormPlugin } from './batch-outputs-plugin';

View File

@ -7,3 +7,4 @@ export * from './components';
export * from './effects'; export * from './effects';
export * from './utils'; export * from './utils';
export * from './typings'; export * from './typings';
export * from './form-plugins';

View File

@ -4,5 +4,5 @@
*/ */
export * from './format-legacy-refs'; export * from './format-legacy-refs';
export * from './json-schema';
export * from './svg-icon'; export * from './svg-icon';
export * from './json-schema';

View File

@ -42,7 +42,10 @@ export namespace JsonSchemaUtils {
.map(([key, _property]) => ({ .map(([key, _property]) => ({
key, key,
type: schemaToAST(_property), type: schemaToAST(_property),
meta: { description: _property.description }, meta: {
title: _property.title,
description: _property.description,
},
})), })),
}); });
case 'array': case 'array':
@ -114,7 +117,18 @@ export namespace JsonSchemaUtils {
type: 'object', type: 'object',
properties: drilldown properties: drilldown
? Object.fromEntries( ? Object.fromEntries(
Object.entries(typeAST.properties).map(([key, value]) => [key, astToSchema(value)!]) typeAST.properties.map((property) => {
const schema = astToSchema(property.type);
if (property.meta?.title && schema) {
schema.title = property.meta.title;
}
if (property.meta?.description && schema) {
schema.description = property.meta.description;
}
return [property.key, schema!];
})
) )
: {}, : {},
}; };