diff --git a/webapp/packages/core-ui/src/Form/FormPart.ts b/webapp/packages/core-ui/src/Form/FormPart.ts index f5a90ba741f..2f50a1ef766 100644 --- a/webapp/packages/core-ui/src/Form/FormPart.ts +++ b/webapp/packages/core-ui/src/Form/FormPart.ts @@ -13,6 +13,7 @@ import { isObjectsEqual, schema } from '@cloudbeaver/core-utils'; import type { IFormPart } from './IFormPart.js'; import type { IFormState } from './IFormState.js'; import { formSubmitContext } from './formSubmitContext.js'; +import { safeParseSchema } from './safeParseSchema.js'; import { formValidationContext } from './formValidationContext.js'; export abstract class FormPart implements IFormPart { @@ -165,14 +166,14 @@ export abstract class FormPart impl private async handleValidation(data: IFormState, contexts: IExecutionContextProvider>): Promise { const validation = contexts.getContext(formValidationContext); - try { - if (this.schema) { - const parsedState = this.schema.parse(toJS(this.state)); - this.setState(observable(parsedState)); + if (this.schema) { + const result = safeParseSchema(this.schema, toJS(this.state), validation); + + if (!result.success) { + return; } - } catch (e: any) { - validation.error(schema.prettifyError(e)); - return; + + this.setState(observable(result.data)); } try { diff --git a/webapp/packages/core-ui/src/Form/safeParseSchema.ts b/webapp/packages/core-ui/src/Form/safeParseSchema.ts new file mode 100644 index 00000000000..81bd8e8c1dc --- /dev/null +++ b/webapp/packages/core-ui/src/Form/safeParseSchema.ts @@ -0,0 +1,27 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2026 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ +import { schema } from '@cloudbeaver/core-utils'; + +import type { IFormValidationContext } from './formValidationContext.js'; + +export function safeParseSchema(zodSchema: schema.ZodType, value: unknown, validation: IFormValidationContext): schema.ZodSafeParseResult { + const result = zodSchema.safeParse(value); + + if (!result.success) { + const seenMessages = new Set(); + for (const issue of result.error.issues) { + const message = issue.message || schema.prettifyError(result.error); + if (!seenMessages.has(message)) { + seenMessages.add(message); + validation.error(message); + } + } + } + + return result; +} diff --git a/webapp/packages/core-ui/src/index.ts b/webapp/packages/core-ui/src/index.ts index 113782aea86..0a748846144 100644 --- a/webapp/packages/core-ui/src/index.ts +++ b/webapp/packages/core-ui/src/index.ts @@ -35,6 +35,7 @@ export * from './Form/FormBaseService.js'; export * from './Form/FormMode.js'; export * from './Form/FormState.js'; export * from './Form/FormPart.js'; +export * from './Form/safeParseSchema.js'; export * from './Form/formStateContext.js'; export * from './Form/formStatusContext.js'; export * from './Form/formValidationContext.js'; diff --git a/webapp/packages/plugin-codemirror6/package.json b/webapp/packages/plugin-codemirror6/package.json index 8996eb85709..19bca042cd2 100644 --- a/webapp/packages/plugin-codemirror6/package.json +++ b/webapp/packages/plugin-codemirror6/package.json @@ -36,6 +36,7 @@ "@codemirror/lang-sql": "^6", "@codemirror/lang-xml": "^6", "@codemirror/language": "^6", + "@codemirror/lint": "^6", "@codemirror/merge": "^6", "@codemirror/search": "^6", "@codemirror/state": "^6", diff --git a/webapp/packages/plugin-codemirror6/src/index.ts b/webapp/packages/plugin-codemirror6/src/index.ts index 7a124789bc7..3ac394984fb 100644 --- a/webapp/packages/plugin-codemirror6/src/index.ts +++ b/webapp/packages/plugin-codemirror6/src/index.ts @@ -1,6 +1,6 @@ /* * CloudBeaver - Cloud Database Manager - * Copyright (C) 2020-2025 DBeaver Corp and others + * Copyright (C) 2020-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. @@ -26,9 +26,11 @@ export * from '@codemirror/state'; export * from '@codemirror/autocomplete'; export * from './highlightNewLine.js'; +export { history } from '@codemirror/commands'; export { html as HTML_EDITOR } from '@codemirror/lang-html'; export { javascript as JAVASCRIPT_EDITOR } from '@codemirror/lang-javascript'; -export { json as JSON_EDITOR } from '@codemirror/lang-json'; +export { json as JSON_EDITOR, jsonParseLinter } from '@codemirror/lang-json'; +export { linter, lintGutter } from '@codemirror/lint'; export { sql as SQL_EDITOR, SQLDialect } from '@codemirror/lang-sql'; export { xml as XML_EDITOR } from '@codemirror/lang-xml'; diff --git a/webapp/yarn.lock b/webapp/yarn.lock index bfded623ae6..368e2850bb6 100644 --- a/webapp/yarn.lock +++ b/webapp/yarn.lock @@ -2587,6 +2587,7 @@ __metadata: "@codemirror/lang-sql": "npm:^6" "@codemirror/lang-xml": "npm:^6" "@codemirror/language": "npm:^6" + "@codemirror/lint": "npm:^6" "@codemirror/merge": "npm:^6" "@codemirror/search": "npm:^6" "@codemirror/state": "npm:^6"