From 695d3b7a0314a2d80241b2afebbcfbbfb5d84db7 Mon Sep 17 00:00:00 2001 From: twwu Date: Tue, 25 Mar 2025 18:10:22 +0800 Subject: [PATCH] feat: enhance JSON schema validation and error handling in configuration modal --- .../json-schema-config.tsx | 38 +++++++-------- .../generated-result.tsx | 18 ++++---- .../components/workflow/nodes/llm/utils.ts | 46 +++++++++---------- 3 files changed, 49 insertions(+), 53 deletions(-) diff --git a/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/json-schema-config.tsx b/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/json-schema-config.tsx index b61579ada2..71cff8fe95 100644 --- a/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/json-schema-config.tsx +++ b/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/json-schema-config.tsx @@ -9,7 +9,7 @@ import { useTranslation } from 'react-i18next' import Button from '@/app/components/base/button' import VisualEditor from './visual-editor' import SchemaEditor from './schema-editor' -import { jsonToSchema } from '../../utils' +import { getValidationErrorMessage, jsonToSchema, validateSchemaAgainstDraft7 } from '../../utils' import { MittProvider, VisualEditorContextProvider } from './visual-editor/context' import ErrorMessage from './error-message' @@ -59,15 +59,15 @@ const JsonSchemaConfig: FC = ({ try { const schema = JSON.parse(json) setParseError(null) - // const ajvError = validateSchemaAgainstDraft7(schema) - // if (ajvError.length > 0) { - // setValidationError(getValidationErrorMessage(ajvError)) - // return - // } - // else { - setJsonSchema(schema) - setValidationError('') - // } + const ajvError = validateSchemaAgainstDraft7(schema) + if (ajvError.length > 0) { + setValidationError(getValidationErrorMessage(ajvError)) + return + } + else { + setJsonSchema(schema) + setValidationError('') + } } catch (error) { setValidationError('') @@ -117,15 +117,15 @@ const JsonSchemaConfig: FC = ({ try { schema = JSON.parse(json) setParseError(null) - // const ajvError = validateSchemaAgainstDraft7(schema) - // if (ajvError.length > 0) { - // setValidationError(getValidationErrorMessage(ajvError)) - // return - // } - // else { - setJsonSchema(schema) - setValidationError('') - // } + const ajvError = validateSchemaAgainstDraft7(schema) + if (ajvError.length > 0) { + setValidationError(getValidationErrorMessage(ajvError)) + return + } + else { + setJsonSchema(schema) + setValidationError('') + } } catch (error) { setValidationError('') diff --git a/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/json-schema-generator/generated-result.tsx b/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/json-schema-generator/generated-result.tsx index 2c96702450..56a174c176 100644 --- a/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/json-schema-generator/generated-result.tsx +++ b/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/json-schema-generator/generated-result.tsx @@ -5,7 +5,7 @@ import { useTranslation } from 'react-i18next' import Button from '@/app/components/base/button' import CodeEditor from '../code-editor' import ErrorMessage from '../error-message' -// import { getValidationErrorMessage, validateSchemaAgainstDraft7 } from '../../../utils' +import { getValidationErrorMessage, validateSchemaAgainstDraft7 } from '../../../utils' type GeneratedResultProps = { schema: SchemaRoot @@ -44,14 +44,14 @@ const GeneratedResult: FC = ({ const jsonSchema = useMemo(() => formatJSON(schema), [schema]) const handleApply = useCallback(() => { - // const ajvError = validateSchemaAgainstDraft7(schema) - // if (ajvError.length > 0) { - // setValidationError(getValidationErrorMessage(ajvError)) - // } - // else { - onApply() - setValidationError('') - // } + const ajvError = validateSchemaAgainstDraft7(schema) + if (ajvError.length > 0) { + setValidationError(getValidationErrorMessage(ajvError)) + } + else { + onApply() + setValidationError('') + } }, [schema, onApply]) return ( diff --git a/web/app/components/workflow/nodes/llm/utils.ts b/web/app/components/workflow/nodes/llm/utils.ts index 0daa3c4476..0b388bf72f 100644 --- a/web/app/components/workflow/nodes/llm/utils.ts +++ b/web/app/components/workflow/nodes/llm/utils.ts @@ -1,8 +1,7 @@ import { ArrayType, Type } from './types' import type { ArrayItems, Field, LLMNodeType } from './types' -// import Ajv, { type ErrorObject } from 'ajv' -// import draft7MetaSchema from 'ajv/dist/refs/json-schema-draft-07.json' -// import produce from 'immer' +import Ajv, { type ErrorObject } from 'ajv' +import produce from 'immer' export const checkNodeValid = (payload: LLMNodeType) => { return true @@ -83,29 +82,26 @@ export const findPropertyWithPath = (target: any, path: string[]) => { return current } -// const ajv = new Ajv({ -// allErrors: true, -// verbose: true, -// validateSchema: true, -// meta: false, -// }) -// ajv.addMetaSchema(draft7MetaSchema) +const ajv = new Ajv({ + allErrors: true, + verbose: true, +}) -// export const validateSchemaAgainstDraft7 = (schemaToValidate: any) => { -// const schema = produce(schemaToValidate, (draft: any) => { -// // Make sure the schema has the $schema property for draft-07 -// if (!draft.$schema) -// draft.$schema = 'http://json-schema.org/draft-07/schema#' -// }) +export const validateSchemaAgainstDraft7 = (schemaToValidate: any) => { + const schema = produce(schemaToValidate, (draft: any) => { + // Make sure the schema has the $schema property for draft-07 + if (!draft.$schema) + draft.$schema = 'http://json-schema.org/draft-07/schema#' + }) -// const valid = ajv.validateSchema(schema) + const valid = ajv.validateSchema(schema) -// return valid ? [] : ajv.errors || [] -// } + return valid ? [] : ajv.errors || [] +} -// export const getValidationErrorMessage = (errors: ErrorObject[]) => { -// const message = errors.map((error) => { -// return `Error: ${error.instancePath} ${error.message} Details: ${JSON.stringify(error.params)}` -// }).join('; ') -// return message -// } +export const getValidationErrorMessage = (errors: ErrorObject[]) => { + const message = errors.map((error) => { + return `Error: ${error.instancePath} ${error.message} Details: ${JSON.stringify(error.params)}` + }).join('; ') + return message +}