|
@@ -1,11 +1,221 @@
|
|
|
import { SourceCode } from '@theme';
|
|
import { SourceCode } from '@theme';
|
|
|
|
|
+import { BasicStory } from 'components/form-materials/validate/validate-flow-value';
|
|
|
|
|
|
|
|
-:::warning
|
|
|
|
|
-The material has been developed and the documentation is still being improved. Contributions are welcome.
|
|
|
|
|
-:::
|
|
|
|
|
|
|
+# validateFlowValue
|
|
|
|
|
|
|
|
-# validateFlowValue (WIP)
|
|
|
|
|
|
|
+validateFlowValue is a validation function for verifying the **requiredness and variable reference validity** of [`FlowValue`](../common/flow-value).
|
|
|
|
|
+
|
|
|
|
|
+## Case Demonstration
|
|
|
|
|
+
|
|
|
|
|
+### Basic Usage
|
|
|
|
|
+
|
|
|
|
|
+<BasicStory />
|
|
|
|
|
+
|
|
|
|
|
+```tsx pure title="form-meta.tsx"
|
|
|
|
|
+import { validateFlowValue } from '@flowgram.ai/form-materials';
|
|
|
|
|
+
|
|
|
|
|
+const formMeta = {
|
|
|
|
|
+ validate: {
|
|
|
|
|
+ dynamic_value_input: ({ value, context }) =>
|
|
|
|
|
+ validateFlowValue(value, {
|
|
|
|
|
+ node: context.node,
|
|
|
|
|
+ errorMessages: {
|
|
|
|
|
+ required: 'Value is required',
|
|
|
|
|
+ unknownVariable: 'Unknown Variable',
|
|
|
|
|
+ },
|
|
|
|
|
+ }),
|
|
|
|
|
+ required_dynamic_value_input: ({ value, context }) =>
|
|
|
|
|
+ validateFlowValue(value, {
|
|
|
|
|
+ node: context.node,
|
|
|
|
|
+ required: true,
|
|
|
|
|
+ errorMessages: {
|
|
|
|
|
+ required: 'Value is required',
|
|
|
|
|
+ unknownVariable: 'Unknown Variable',
|
|
|
|
|
+ },
|
|
|
|
|
+ }),
|
|
|
|
|
+ prompt_editor: ({ value, context }) =>
|
|
|
|
|
+ validateFlowValue(value, {
|
|
|
|
|
+ node: context.node,
|
|
|
|
|
+ required: true,
|
|
|
|
|
+ errorMessages: {
|
|
|
|
|
+ required: 'Prompt is required',
|
|
|
|
|
+ unknownVariable: 'Unknown Variable In Template',
|
|
|
|
|
+ },
|
|
|
|
|
+ }),
|
|
|
|
|
+ },
|
|
|
|
|
+ render: ({ form }) => (
|
|
|
|
|
+ <>
|
|
|
|
|
+ <FormHeader />
|
|
|
|
|
+ <b>Validate variable valid</b>
|
|
|
|
|
+ <Field<any> name="dynamic_value_input">
|
|
|
|
|
+ {({ field, fieldState }) => (
|
|
|
|
|
+ <>
|
|
|
|
|
+ <DynamicValueInput
|
|
|
|
|
+ value={field.value}
|
|
|
|
|
+ onChange={(value) => field.onChange(value)}
|
|
|
|
|
+ />
|
|
|
|
|
+ <span style={{ color: 'red' }}>
|
|
|
|
|
+ {fieldState.errors?.map((e) => e.message).join('\n')}
|
|
|
|
|
+ </span>
|
|
|
|
|
+ </>
|
|
|
|
|
+ )}
|
|
|
|
|
+ </Field>
|
|
|
|
|
+ <br />
|
|
|
|
|
+ <b>Validate required value</b>
|
|
|
|
|
+ <Field<any> name="required_dynamic_value_input">
|
|
|
|
|
+ {({ field, fieldState }) => (
|
|
|
|
|
+ <>
|
|
|
|
|
+ <DynamicValueInput
|
|
|
|
|
+ value={field.value}
|
|
|
|
|
+ onChange={(value) => field.onChange(value)}
|
|
|
|
|
+ />
|
|
|
|
|
+ <span style={{ color: 'red' }}>
|
|
|
|
|
+ {fieldState.errors?.map((e) => e.message).join('\n')}
|
|
|
|
|
+ </span>
|
|
|
|
|
+ </>
|
|
|
|
|
+ )}
|
|
|
|
|
+ </Field>
|
|
|
|
|
+ <br />
|
|
|
|
|
+ <b>Validate required and variables valid in prompt</b>
|
|
|
|
|
+ <Field<any> name="prompt_editor">
|
|
|
|
|
+ {({ field, fieldState }) => (
|
|
|
|
|
+ <>
|
|
|
|
|
+ <PromptEditorWithVariables
|
|
|
|
|
+ value={field.value}
|
|
|
|
|
+ onChange={(value) => field.onChange(value)}
|
|
|
|
|
+ />
|
|
|
|
|
+ <span style={{ color: 'red' }}>
|
|
|
|
|
+ {fieldState.errors?.map((e) => e.message).join('\n')}
|
|
|
|
|
+ </span>
|
|
|
|
|
+ </>
|
|
|
|
|
+ )}
|
|
|
|
|
+ </Field>
|
|
|
|
|
+ <br />
|
|
|
|
|
+ <Button onClick={() => form.validate()}>Trigger Validate</Button>
|
|
|
|
|
+ </>
|
|
|
|
|
+ ),
|
|
|
|
|
+};
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## API Reference
|
|
|
|
|
+
|
|
|
|
|
+### validateFlowValue Function
|
|
|
|
|
+
|
|
|
|
|
+```typescript
|
|
|
|
|
+export function validateFlowValue(value: IFlowValue | undefined, ctx: Context): {
|
|
|
|
|
+ level: FeedbackLevel.Error;
|
|
|
|
|
+ message: string;
|
|
|
|
|
+} | undefined;
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+#### Parameters
|
|
|
|
|
+
|
|
|
|
|
+| Parameter | Type | Description |
|
|
|
|
|
+|-----------|------|-------------|
|
|
|
|
|
+| `value` | `IFlowValue \| undefined` | The FlowValue to validate |
|
|
|
|
|
+| `ctx` | `Context` | Validation context |
|
|
|
|
|
+
|
|
|
|
|
+#### Context Interface
|
|
|
|
|
+
|
|
|
|
|
+```typescript
|
|
|
|
|
+interface Context {
|
|
|
|
|
+ node: FlowNodeEntity;
|
|
|
|
|
+ required?: boolean; // Whether required
|
|
|
|
|
+ errorMessages?: {
|
|
|
|
|
+ required?: string; // Required error message
|
|
|
|
|
+ unknownVariable?: string; // Unknown variable error message
|
|
|
|
|
+ };
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+#### Return Value
|
|
|
|
|
+
|
|
|
|
|
+- If validation passes, returns `undefined`
|
|
|
|
|
+- If validation fails, returns an object containing error level and error message
|
|
|
|
|
+
|
|
|
|
|
+### Supported Validation Types
|
|
|
|
|
+
|
|
|
|
|
+1. **Required Validation**: When `required` is set to `true`, verifies if the value exists and is not empty
|
|
|
|
|
+2. **Reference Variable Validation**: For values of type `ref`, verifies if the referenced variable exists
|
|
|
|
|
+3. **Template Variable Validation**: For values of type `template`, verifies if all variables referenced in the template exist
|
|
|
|
|
+
|
|
|
|
|
+## Source Code Guide
|
|
|
|
|
|
|
|
<SourceCode
|
|
<SourceCode
|
|
|
- href="https.://github.com/bytedance/flowgram.ai/tree/main/packages/materials/form-materials/src/validate/validate-flow-value"
|
|
|
|
|
-/>
|
|
|
|
|
|
|
+ href="https://github.com/bytedance/flowgram.ai/tree/main/packages/materials/form-materials/src/validate/validate-flow-value/index.ts"
|
|
|
|
|
+/>
|
|
|
|
|
+
|
|
|
|
|
+Use the CLI command to copy the source code locally:
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+npx @flowgram.ai/cli@latest materials validate/validate-flow-value
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### Directory Structure
|
|
|
|
|
+
|
|
|
|
|
+```
|
|
|
|
|
+validate-flow-value/
|
|
|
|
|
+└── index.tsx # Main function implementation, containing validateFlowValue core logic
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### Core Implementation
|
|
|
|
|
+
|
|
|
|
|
+#### Required Validation Logic
|
|
|
|
|
+
|
|
|
|
|
+```typescript
|
|
|
|
|
+if (required && (isNil(value) || isNil(value?.content) || value?.content === '')) {
|
|
|
|
|
+ return {
|
|
|
|
|
+ level: FeedbackLevel.Error,
|
|
|
|
|
+ message: requiredMessage,
|
|
|
|
|
+ };
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+#### Reference Variable Validation Logic
|
|
|
|
|
+
|
|
|
|
|
+```typescript
|
|
|
|
|
+if (value?.type === 'ref') {
|
|
|
|
|
+ const variable = node.scope.available.getByKeyPath(value?.content || []);
|
|
|
|
|
+ if (!variable) {
|
|
|
|
|
+ return {
|
|
|
|
|
+ level: FeedbackLevel.Error,
|
|
|
|
|
+ message: unknownVariableMessage,
|
|
|
|
|
+ };
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+#### Template Variable Validation Logic
|
|
|
|
|
+
|
|
|
|
|
+```typescript
|
|
|
|
|
+if (value?.type === 'template') {
|
|
|
|
|
+ const allRefs = FlowValueUtils.getTemplateKeyPaths(value);
|
|
|
|
|
+
|
|
|
|
|
+ for (const ref of allRefs) {
|
|
|
|
|
+ const variable = node.scope.available.getByKeyPath(ref);
|
|
|
|
|
+ if (!variable) {
|
|
|
|
|
+ return {
|
|
|
|
|
+ level: FeedbackLevel.Error,
|
|
|
|
|
+ message: unknownVariableMessage,
|
|
|
|
|
+ };
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### Flowgram APIs Used
|
|
|
|
|
+
|
|
|
|
|
+[**@flowgram.ai/editor**](https://github.com/bytedance/flowgram.ai/tree/main/packages/client/editor)
|
|
|
|
|
+- [`FeedbackLevel`](https://flowgram.ai/auto-docs/editor/enums/FeedbackLevel): Feedback level enum
|
|
|
|
|
+
|
|
|
|
|
+### Dependencies on Other Materials
|
|
|
|
|
+
|
|
|
|
|
+[**FlowValue**](../common/flow-value)
|
|
|
|
|
+- `IFlowValue`: FlowValue type definition
|
|
|
|
|
+- `FlowValueUtils`: FlowValue utility class
|
|
|
|
|
+ - `getTemplateKeyPaths`: Method to extract all variable reference paths from templates
|
|
|
|
|
+
|
|
|
|
|
+### Third-party Libraries
|
|
|
|
|
+
|
|
|
|
|
+[**lodash-es**](https://lodash.com/)
|
|
|
|
|
+- `isNil`: Checks if a value is null or undefined
|