feat: add json-stringify node (#215)
Co-authored-by: zengxiaohui <zengxiaohui@bytedance.com>
This commit is contained in:
parent
183d0324bb
commit
0965d69acc
|
|
@ -56,7 +56,7 @@ export const getEnabledNodeTypes = (_params: {
|
|||
[StandardNodeType.DatabaseDelete]: true,
|
||||
[StandardNodeType.DatabaseCreate]: true,
|
||||
// [StandardNodeType.JsonParser]: true,
|
||||
// [StandardNodeType.JsonStringify]: true,
|
||||
[StandardNodeType.JsonStringify]: true,
|
||||
// [StandardNodeType.UpdateConversation]: true,
|
||||
// [StandardNodeType.DeleteConversation]: true,
|
||||
// [StandardNodeType.QueryConversationList]: true,
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import { PluginContent } from '@/node-registries/plugin';
|
|||
import { OutputContent } from '@/node-registries/output';
|
||||
import { LtmContent } from '@/node-registries/ltm';
|
||||
import { LoopContent } from '@/node-registries/loop';
|
||||
import { JsonStringifyContent } from '@/node-registries/json-stringify';
|
||||
import { IntentContent } from '@/node-registries/intent';
|
||||
import { InputContent } from '@/node-registries/input';
|
||||
import { ImageCanvasContent } from '@/node-registries/image-canvas';
|
||||
|
|
@ -89,6 +90,7 @@ const ContentMap = {
|
|||
[StandardNodeType.TriggerRead]: TriggerReadContent,
|
||||
[StandardNodeType.Api]: PluginContent,
|
||||
[StandardNodeType.Variable]: VariableContent,
|
||||
[StandardNodeType.JsonStringify]: JsonStringifyContent,
|
||||
// cli 脚本插入标识(registry),请勿修改/删除此行注释
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -47,4 +47,5 @@ export { IF_NODE_REGISTRY } from './if';
|
|||
export { PLUGIN_NODE_REGISTRY } from './plugin';
|
||||
export { SUB_WORKFLOW_NODE_REGISTRY } from './sub-workflow';
|
||||
export { VARIABLE_NODE_REGISTRY } from './variable';
|
||||
export { JSON_STRINGIFY_NODE_REGISTRY } from './json-stringify';
|
||||
// cli 脚本插入标识(registry),请勿修改/删除此行注释
|
||||
|
|
|
|||
|
|
@ -0,0 +1,68 @@
|
|||
import {
|
||||
FieldArray,
|
||||
type FieldArrayRenderProps,
|
||||
} from '@flowgram-adapter/free-layout-editor';
|
||||
import type { ViewVariableType, InputValueVO } from '@coze-workflow/base';
|
||||
import { I18n } from '@coze-arch/i18n';
|
||||
|
||||
import { useReadonly } from '@/nodes-v2/hooks/use-readonly';
|
||||
import { ValueExpressionInputField } from '@/node-registries/common/fields';
|
||||
import { FieldArrayItem, FieldRows, Section, type FieldProps } from '@/form';
|
||||
|
||||
interface InputsFieldProps extends FieldProps<InputValueVO[]> {
|
||||
title?: string;
|
||||
paramsTitle?: string;
|
||||
expressionTitle?: string;
|
||||
disabledTypes?: ViewVariableType[];
|
||||
onAppend?: () => InputValueVO;
|
||||
inputPlaceholder?: string;
|
||||
literalDisabled?: boolean;
|
||||
showEmptyText?: boolean;
|
||||
nthCannotDeleted?: number;
|
||||
}
|
||||
|
||||
export const InputsField = ({
|
||||
name,
|
||||
defaultValue,
|
||||
title,
|
||||
tooltip,
|
||||
disabledTypes,
|
||||
inputPlaceholder,
|
||||
literalDisabled,
|
||||
showEmptyText = true,
|
||||
}: InputsFieldProps) => {
|
||||
const readonly = useReadonly();
|
||||
return (
|
||||
<FieldArray<InputValueVO> name={name} defaultValue={defaultValue}>
|
||||
{({ field }: FieldArrayRenderProps<InputValueVO>) => {
|
||||
const { value = [] } = field;
|
||||
const length = value?.length ?? 0;
|
||||
const isEmpty = !length;
|
||||
return (
|
||||
<Section
|
||||
title={title}
|
||||
tooltip={tooltip}
|
||||
isEmpty={showEmptyText && isEmpty}
|
||||
emptyText={I18n.t('workflow_inputs_empty')}
|
||||
>
|
||||
<FieldRows>
|
||||
{field.map((item, index) => (
|
||||
<FieldArrayItem key={item.key} disableRemove hiddenRemove>
|
||||
<div style={{ flex: 3 }}>
|
||||
<ValueExpressionInputField
|
||||
name={`${name}.${index}.input`}
|
||||
disabledTypes={disabledTypes}
|
||||
readonly={readonly}
|
||||
inputPlaceholder={inputPlaceholder}
|
||||
literalDisabled={literalDisabled}
|
||||
/>
|
||||
</div>
|
||||
</FieldArrayItem>
|
||||
))}
|
||||
</FieldRows>
|
||||
</Section>
|
||||
);
|
||||
}}
|
||||
</FieldArray>
|
||||
);
|
||||
};
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
import { nanoid } from 'nanoid';
|
||||
import { ViewVariableType } from '@coze-workflow/variable';
|
||||
|
||||
// 入参路径,试运行等功能依赖该路径提取参数
|
||||
export const INPUT_PATH = 'inputs.inputParameters';
|
||||
|
||||
// 定义固定出参
|
||||
export const OUTPUTS = [
|
||||
{
|
||||
key: nanoid(),
|
||||
name: 'output',
|
||||
type: ViewVariableType.String,
|
||||
},
|
||||
];
|
||||
|
||||
export const DEFAULT_INPUTS = [{ name: 'input' }];
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
import { type NodeDataDTO } from '@coze-workflow/base';
|
||||
|
||||
import { type FormData } from './types';
|
||||
import { OUTPUTS } from './constants';
|
||||
|
||||
/**
|
||||
* 节点后端数据 -> 前端表单数据
|
||||
*/
|
||||
export const transformOnInit = (value: NodeDataDTO) => ({
|
||||
...(value ?? {}),
|
||||
outputs: value?.outputs ?? OUTPUTS,
|
||||
});
|
||||
|
||||
/**
|
||||
* 前端表单数据 -> 节点后端数据
|
||||
* @param value
|
||||
* @returns
|
||||
*/
|
||||
export const transformOnSubmit = (value: FormData): NodeDataDTO =>
|
||||
value as unknown as NodeDataDTO;
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
import {
|
||||
ValidateTrigger,
|
||||
type FormMetaV2,
|
||||
} from '@flowgram-adapter/free-layout-editor';
|
||||
|
||||
import { createValueExpressionInputValidate } from '@/node-registries/common/validators';
|
||||
import {
|
||||
fireNodeTitleChange,
|
||||
provideNodeOutputVariablesEffect,
|
||||
} from '@/node-registries/common/effects';
|
||||
|
||||
import { type FormData } from './types';
|
||||
import { FormRender } from './form';
|
||||
import { transformOnInit, transformOnSubmit } from './data-transformer';
|
||||
|
||||
export const JSON_STRINGIFY_FORM_META: FormMetaV2<FormData> = {
|
||||
// 节点表单渲染
|
||||
render: () => <FormRender />,
|
||||
|
||||
// 验证触发时机
|
||||
validateTrigger: ValidateTrigger.onChange,
|
||||
|
||||
// 验证规则
|
||||
validate: {
|
||||
// 必填
|
||||
'inputs.inputParameters.0.input': createValueExpressionInputValidate({
|
||||
required: true,
|
||||
}),
|
||||
},
|
||||
|
||||
// 副作用管理
|
||||
effect: {
|
||||
nodeMeta: fireNodeTitleChange,
|
||||
outputs: provideNodeOutputVariablesEffect,
|
||||
},
|
||||
|
||||
// 节点后端数据 -> 前端表单数据
|
||||
formatOnInit: transformOnInit,
|
||||
|
||||
// 前端表单数据 -> 节点后端数据
|
||||
formatOnSubmit: transformOnSubmit,
|
||||
};
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
import { I18n } from '@coze-arch/i18n';
|
||||
|
||||
import { NodeConfigForm } from '@/node-registries/common/components';
|
||||
|
||||
import { OutputsField } from '../common/fields';
|
||||
import { INPUT_PATH } from './constants';
|
||||
import { InputsField } from './components/inputs';
|
||||
|
||||
export const FormRender = () => (
|
||||
<NodeConfigForm>
|
||||
<InputsField
|
||||
name={INPUT_PATH}
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
defaultValue={[{ name: 'input' } as any]}
|
||||
title={I18n.t('node_http_request_params')}
|
||||
tooltip={I18n.t('workflow_250429_03')}
|
||||
required={false}
|
||||
layout="horizontal"
|
||||
/>
|
||||
|
||||
<OutputsField
|
||||
title={I18n.t('workflow_detail_node_output')}
|
||||
tooltip={I18n.t('node_http_response_data')}
|
||||
id="jsonStringify-node-outputs"
|
||||
name="outputs"
|
||||
topLevelReadonly={true}
|
||||
customReadonly
|
||||
/>
|
||||
</NodeConfigForm>
|
||||
);
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
export { JSON_STRINGIFY_NODE_REGISTRY } from './node-registry';
|
||||
export { JsonStringifyContent } from './node-content';
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
import { InputParameters, Outputs } from '../common/components';
|
||||
|
||||
export function JsonStringifyContent() {
|
||||
return (
|
||||
<>
|
||||
<InputParameters />
|
||||
<Outputs />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
import {
|
||||
DEFAULT_NODE_META_PATH,
|
||||
DEFAULT_OUTPUTS_PATH,
|
||||
} from '@coze-workflow/nodes';
|
||||
import {
|
||||
StandardNodeType,
|
||||
type WorkflowNodeRegistry,
|
||||
} from '@coze-workflow/base';
|
||||
|
||||
import { test, type NodeTestMeta } from './node-test';
|
||||
import { JSON_STRINGIFY_FORM_META } from './form-meta';
|
||||
import { INPUT_PATH } from './constants';
|
||||
|
||||
export const JSON_STRINGIFY_NODE_REGISTRY: WorkflowNodeRegistry<NodeTestMeta> =
|
||||
{
|
||||
type: StandardNodeType.JsonStringify,
|
||||
meta: {
|
||||
nodeDTOType: StandardNodeType.JsonStringify,
|
||||
size: { width: 360, height: 130.7 },
|
||||
nodeMetaPath: DEFAULT_NODE_META_PATH,
|
||||
outputsPath: DEFAULT_OUTPUTS_PATH,
|
||||
inputParametersPath: INPUT_PATH,
|
||||
test,
|
||||
},
|
||||
formMeta: JSON_STRINGIFY_FORM_META,
|
||||
};
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
import { FlowNodeFormData } from '@flowgram-adapter/free-layout-editor';
|
||||
|
||||
import {
|
||||
type NodeTestMeta,
|
||||
generateParametersToProperties,
|
||||
} from '@/test-run-kit';
|
||||
|
||||
export const test: NodeTestMeta = {
|
||||
generateFormInputProperties(node) {
|
||||
const formData = node
|
||||
.getData(FlowNodeFormData)
|
||||
.formModel.getFormItemValueByPath('/');
|
||||
const parameters = formData?.inputs?.inputParameters;
|
||||
|
||||
return generateParametersToProperties(parameters, {
|
||||
node,
|
||||
});
|
||||
},
|
||||
};
|
||||
export type { NodeTestMeta };
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
import { type InputValueVO } from '@coze-workflow/base';
|
||||
|
||||
export interface FormData {
|
||||
inputs: { inputParameters: InputValueVO[] };
|
||||
}
|
||||
|
|
@ -51,6 +51,7 @@ import {
|
|||
PLUGIN_NODE_REGISTRY,
|
||||
SUB_WORKFLOW_NODE_REGISTRY,
|
||||
VARIABLE_NODE_REGISTRY,
|
||||
JSON_STRINGIFY_NODE_REGISTRY,
|
||||
// cli 脚本插入标识(import),请勿修改/删除此行注释
|
||||
} from '@/node-registries';
|
||||
|
||||
|
|
@ -69,6 +70,7 @@ import {
|
|||
|
||||
export const NODES_V2 = [
|
||||
// cli 脚本插入标识(registry),请勿修改/删除此行注释
|
||||
JSON_STRINGIFY_NODE_REGISTRY,
|
||||
IF_NODE_REGISTRY,
|
||||
INTENT_NODE_REGISTRY,
|
||||
SUB_WORKFLOW_NODE_REGISTRY,
|
||||
|
|
|
|||
Loading…
Reference in New Issue