@qoretechnologies/reqraft 0.10.55-pr.124.g77dd26c → 0.10.55
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/CLAUDE.md +25 -0
- package/.tasks/INDEX.md +1 -0
- package/.tasks/STORY_NETWORK_ISOLATION.md +98 -0
- package/README.md +1 -1
- package/design/FORM_ENGINE_COMPACT.md +34 -0
- package/design/FORM_ENGINE_EXPRESSIONS.md +110 -0
- package/design/FORM_ENGINE_FIELD_MIGRATION.md +155 -1
- package/design/IDE_INTEGRATION.md +13 -0
- package/design/RENDER_EXPRESSION_TRANSPORT.md +76 -10
- package/design/SELECT_DIALOG_FLOOR.md +86 -0
- package/design/SMART_EDITOR_UX.md +21 -0
- package/design/UNAVAILABLE_ALLOWED_VALUES.md +226 -0
- package/dist/components/composer/Composer.d.ts +8 -3
- package/dist/components/composer/Composer.d.ts.map +1 -1
- package/dist/components/composer/Composer.js.map +1 -1
- package/dist/components/dpqlEditor/DpqlEditor.d.ts.map +1 -1
- package/dist/components/dpqlEditor/DpqlEditor.js +3 -3
- package/dist/components/dpqlEditor/DpqlEditor.js.map +1 -1
- package/dist/components/dpqlEditor/dpqlHelpers.d.ts +6 -0
- package/dist/components/dpqlEditor/dpqlHelpers.d.ts.map +1 -1
- package/dist/components/dpqlEditor/dpqlHelpers.js +21 -2
- package/dist/components/dpqlEditor/dpqlHelpers.js.map +1 -1
- package/dist/components/dpqlEditor/dpqlProbe.d.ts +37 -0
- package/dist/components/dpqlEditor/dpqlProbe.d.ts.map +1 -0
- package/dist/components/dpqlEditor/dpqlProbe.js +203 -0
- package/dist/components/dpqlEditor/dpqlProbe.js.map +1 -0
- package/dist/components/dpqlEditor/dpqlTags.d.ts +8 -0
- package/dist/components/dpqlEditor/dpqlTags.d.ts.map +1 -1
- package/dist/components/dpqlEditor/dpqlTags.js +5 -1
- package/dist/components/dpqlEditor/dpqlTags.js.map +1 -1
- package/dist/components/dpqlEditor/index.d.ts +4 -0
- package/dist/components/dpqlEditor/index.d.ts.map +1 -1
- package/dist/components/dpqlEditor/index.js +5 -1
- package/dist/components/dpqlEditor/index.js.map +1 -1
- package/dist/components/dpqlEditor/types.d.ts +42 -2
- package/dist/components/dpqlEditor/types.d.ts.map +1 -1
- package/dist/components/dpqlEditor/types.js +0 -4
- package/dist/components/dpqlEditor/types.js.map +1 -1
- package/dist/components/dpqlEditor/useDpqlProbe.d.ts +4 -0
- package/dist/components/dpqlEditor/useDpqlProbe.d.ts.map +1 -0
- package/dist/components/dpqlEditor/useDpqlProbe.js +29 -0
- package/dist/components/dpqlEditor/useDpqlProbe.js.map +1 -0
- package/dist/components/dpqlEditor/useDpqlSession.d.ts +5 -2
- package/dist/components/dpqlEditor/useDpqlSession.d.ts.map +1 -1
- package/dist/components/dpqlEditor/useDpqlSession.js +8 -2
- package/dist/components/dpqlEditor/useDpqlSession.js.map +1 -1
- package/dist/components/form/engine/CompactRow.d.ts.map +1 -1
- package/dist/components/form/engine/CompactRow.js +414 -128
- package/dist/components/form/engine/CompactRow.js.map +1 -1
- package/dist/components/form/engine/CompactToolbar.d.ts.map +1 -1
- package/dist/components/form/engine/CompactToolbar.js +5 -2
- package/dist/components/form/engine/CompactToolbar.js.map +1 -1
- package/dist/components/form/engine/FormEngine.d.ts +273 -22
- package/dist/components/form/engine/FormEngine.d.ts.map +1 -1
- package/dist/components/form/engine/FormEngine.js +669 -192
- package/dist/components/form/engine/FormEngine.js.map +1 -1
- package/dist/components/form/engine/FormFieldsSkeleton.d.ts +48 -0
- package/dist/components/form/engine/FormFieldsSkeleton.d.ts.map +1 -0
- package/dist/components/form/engine/FormFieldsSkeleton.js +41 -0
- package/dist/components/form/engine/FormFieldsSkeleton.js.map +1 -0
- package/dist/components/form/engine/OptionFieldMessages.d.ts +108 -2
- package/dist/components/form/engine/OptionFieldMessages.d.ts.map +1 -1
- package/dist/components/form/engine/OptionFieldMessages.js +203 -13
- package/dist/components/form/engine/OptionFieldMessages.js.map +1 -1
- package/dist/components/form/engine/_structuredData/SchemaDataView.d.ts.map +1 -1
- package/dist/components/form/engine/_structuredData/SchemaDataView.js +68 -5
- package/dist/components/form/engine/_structuredData/SchemaDataView.js.map +1 -1
- package/dist/components/form/engine/compactRowContext.d.ts +15 -1
- package/dist/components/form/engine/compactRowContext.d.ts.map +1 -1
- package/dist/components/form/engine/compactRowContext.js.map +1 -1
- package/dist/components/form/engine/compactRowStyles.d.ts.map +1 -1
- package/dist/components/form/engine/compactRowStyles.js +55 -29
- package/dist/components/form/engine/compactRowStyles.js.map +1 -1
- package/dist/components/form/engine/compactToolbarContext.d.ts +1 -0
- package/dist/components/form/engine/compactToolbarContext.d.ts.map +1 -1
- package/dist/components/form/engine/optionActions.d.ts +37 -1
- package/dist/components/form/engine/optionActions.d.ts.map +1 -1
- package/dist/components/form/engine/optionActions.js +71 -1
- package/dist/components/form/engine/optionActions.js.map +1 -1
- package/dist/components/form/engine/optionsContext.d.ts +22 -0
- package/dist/components/form/engine/optionsContext.d.ts.map +1 -0
- package/dist/components/form/engine/optionsContext.js +20 -0
- package/dist/components/form/engine/optionsContext.js.map +1 -0
- package/dist/components/form/engine/readFirst.d.ts +42 -1
- package/dist/components/form/engine/readFirst.d.ts.map +1 -1
- package/dist/components/form/engine/readFirst.js +76 -8
- package/dist/components/form/engine/readFirst.js.map +1 -1
- package/dist/components/form/engine/rendererTypes.d.ts +42 -3
- package/dist/components/form/engine/rendererTypes.d.ts.map +1 -1
- package/dist/components/form/engine/rendererTypes.js +3 -1
- package/dist/components/form/engine/rendererTypes.js.map +1 -1
- package/dist/components/form/engine/rowFocus.d.ts +30 -0
- package/dist/components/form/engine/rowFocus.d.ts.map +1 -0
- package/dist/components/form/engine/rowFocus.js +93 -0
- package/dist/components/form/engine/rowFocus.js.map +1 -0
- package/dist/components/form/engine/rowMenuContext.d.ts +78 -0
- package/dist/components/form/engine/rowMenuContext.d.ts.map +1 -0
- package/dist/components/form/engine/rowMenuContext.js +103 -0
- package/dist/components/form/engine/rowMenuContext.js.map +1 -0
- package/dist/components/form/engine/rowOpenPicker.d.ts +27 -0
- package/dist/components/form/engine/rowOpenPicker.d.ts.map +1 -0
- package/dist/components/form/engine/rowOpenPicker.js +30 -0
- package/dist/components/form/engine/rowOpenPicker.js.map +1 -0
- package/dist/components/form/engine/typeChoices.d.ts +42 -0
- package/dist/components/form/engine/typeChoices.d.ts.map +1 -0
- package/dist/components/form/engine/typeChoices.js +33 -0
- package/dist/components/form/engine/typeChoices.js.map +1 -0
- package/dist/components/form/expressions/DpqlRendering.d.ts +26 -0
- package/dist/components/form/expressions/DpqlRendering.d.ts.map +1 -0
- package/dist/components/form/expressions/DpqlRendering.js +53 -0
- package/dist/components/form/expressions/DpqlRendering.js.map +1 -0
- package/dist/components/form/expressions/ExpressionField.d.ts +7 -1
- package/dist/components/form/expressions/ExpressionField.d.ts.map +1 -1
- package/dist/components/form/expressions/ExpressionField.js +203 -45
- package/dist/components/form/expressions/ExpressionField.js.map +1 -1
- package/dist/components/form/expressions/argumentPresence.d.ts +84 -0
- package/dist/components/form/expressions/argumentPresence.d.ts.map +1 -0
- package/dist/components/form/expressions/argumentPresence.js +217 -0
- package/dist/components/form/expressions/argumentPresence.js.map +1 -0
- package/dist/components/form/expressions/builder/argumentLabel.d.ts.map +1 -1
- package/dist/components/form/expressions/builder/argumentLabel.js +9 -4
- package/dist/components/form/expressions/builder/argumentLabel.js.map +1 -1
- package/dist/components/form/expressions/builder/index.d.ts +15 -2
- package/dist/components/form/expressions/builder/index.d.ts.map +1 -1
- package/dist/components/form/expressions/builder/index.js +21 -65
- package/dist/components/form/expressions/builder/index.js.map +1 -1
- package/dist/components/form/expressions/builder/renderTemplate.d.ts +4 -1
- package/dist/components/form/expressions/builder/renderTemplate.d.ts.map +1 -1
- package/dist/components/form/expressions/builder/renderTemplate.js +10 -67
- package/dist/components/form/expressions/builder/renderTemplate.js.map +1 -1
- package/dist/components/form/expressions/mockExpressions.d.ts.map +1 -1
- package/dist/components/form/expressions/mockExpressions.js +8 -4
- package/dist/components/form/expressions/mockExpressions.js.map +1 -1
- package/dist/components/form/expressions/renderExpressionToText.d.ts +1 -1
- package/dist/components/form/expressions/renderExpressionToText.d.ts.map +1 -1
- package/dist/components/form/expressions/renderExpressionToText.js +95 -19
- package/dist/components/form/expressions/renderExpressionToText.js.map +1 -1
- package/dist/components/form/expressions/types.d.ts +17 -2
- package/dist/components/form/expressions/types.d.ts.map +1 -1
- package/dist/components/form/expressions/useExpressions.d.ts.map +1 -1
- package/dist/components/form/expressions/useExpressions.js +5 -2
- package/dist/components/form/expressions/useExpressions.js.map +1 -1
- package/dist/components/form/expressions/useRenderExpression.d.ts +7 -16
- package/dist/components/form/expressions/useRenderExpression.d.ts.map +1 -1
- package/dist/components/form/expressions/useRenderExpression.js +50 -126
- package/dist/components/form/expressions/useRenderExpression.js.map +1 -1
- package/dist/components/form/fields/Field.d.ts +21 -0
- package/dist/components/form/fields/Field.d.ts.map +1 -1
- package/dist/components/form/fields/Field.js +54 -8
- package/dist/components/form/fields/Field.js.map +1 -1
- package/dist/components/form/fields/allowed-values/AllowedValues.d.ts +11 -1
- package/dist/components/form/fields/allowed-values/AllowedValues.d.ts.map +1 -1
- package/dist/components/form/fields/allowed-values/AllowedValues.js +52 -8
- package/dist/components/form/fields/allowed-values/AllowedValues.js.map +1 -1
- package/dist/components/form/fields/auto/AutoFormField.d.ts +7 -1
- package/dist/components/form/fields/auto/AutoFormField.d.ts.map +1 -1
- package/dist/components/form/fields/auto/AutoFormField.js +91 -28
- package/dist/components/form/fields/auto/AutoFormField.js.map +1 -1
- package/dist/components/form/fields/date/Date.d.ts +1 -1
- package/dist/components/form/fields/date/Date.d.ts.map +1 -1
- package/dist/components/form/fields/date/Date.js +16 -2
- package/dist/components/form/fields/date/Date.js.map +1 -1
- package/dist/components/form/fields/long-string/LongString.d.ts.map +1 -1
- package/dist/components/form/fields/long-string/LongString.js +14 -2
- package/dist/components/form/fields/long-string/LongString.js.map +1 -1
- package/dist/components/form/fields/multi-select/MultiSelectFormField.d.ts.map +1 -1
- package/dist/components/form/fields/multi-select/MultiSelectFormField.js +50 -4
- package/dist/components/form/fields/multi-select/MultiSelectFormField.js.map +1 -1
- package/dist/components/form/fields/number/Number.d.ts +12 -1
- package/dist/components/form/fields/number/Number.d.ts.map +1 -1
- package/dist/components/form/fields/number/Number.js +6 -3
- package/dist/components/form/fields/number/Number.js.map +1 -1
- package/dist/components/form/fields/rich-text/RichText.d.ts +47 -2
- package/dist/components/form/fields/rich-text/RichText.d.ts.map +1 -1
- package/dist/components/form/fields/rich-text/RichText.js +153 -12
- package/dist/components/form/fields/rich-text/RichText.js.map +1 -1
- package/dist/components/form/fields/select/Select.d.ts.map +1 -1
- package/dist/components/form/fields/select/Select.js +120 -20
- package/dist/components/form/fields/select/Select.js.map +1 -1
- package/dist/components/form/fields/select/SelectCollection.d.ts +166 -9
- package/dist/components/form/fields/select/SelectCollection.d.ts.map +1 -1
- package/dist/components/form/fields/select/SelectCollection.js +200 -7
- package/dist/components/form/fields/select/SelectCollection.js.map +1 -1
- package/dist/components/form/fields/template/ReadOnlyTemplateTag.d.ts +2 -1
- package/dist/components/form/fields/template/ReadOnlyTemplateTag.d.ts.map +1 -1
- package/dist/components/form/fields/template/ReadOnlyTemplateTag.js +3 -2
- package/dist/components/form/fields/template/ReadOnlyTemplateTag.js.map +1 -1
- package/dist/components/form/fields/template/TemplateField.d.ts +34 -2
- package/dist/components/form/fields/template/TemplateField.d.ts.map +1 -1
- package/dist/components/form/fields/template/TemplateField.js +606 -58
- package/dist/components/form/fields/template/TemplateField.js.map +1 -1
- package/dist/components/form/fields/template/TemplateText.d.ts +36 -0
- package/dist/components/form/fields/template/TemplateText.d.ts.map +1 -0
- package/dist/components/form/fields/template/TemplateText.js +80 -0
- package/dist/components/form/fields/template/TemplateText.js.map +1 -0
- package/dist/components/form/index.d.ts +2 -0
- package/dist/components/form/index.d.ts.map +1 -1
- package/dist/components/form/index.js +4 -0
- package/dist/components/form/index.js.map +1 -1
- package/dist/components/smartEditor/SmartEditor.d.ts.map +1 -1
- package/dist/components/smartEditor/SmartEditor.js +29 -8
- package/dist/components/smartEditor/SmartEditor.js.map +1 -1
- package/dist/components/smartEditor/useLspSession.d.ts +5 -1
- package/dist/components/smartEditor/useLspSession.d.ts.map +1 -1
- package/dist/components/smartEditor/useLspSession.js +16 -2
- package/dist/components/smartEditor/useLspSession.js.map +1 -1
- package/dist/components/supportTicket/TicketReplyBox.d.ts +8 -4
- package/dist/components/supportTicket/TicketReplyBox.d.ts.map +1 -1
- package/dist/components/supportTicket/TicketReplyBox.js.map +1 -1
- package/dist/helpers/common.d.ts.map +1 -1
- package/dist/helpers/common.js +7 -3
- package/dist/helpers/common.js.map +1 -1
- package/dist/helpers/dpqlDetection.d.ts +58 -0
- package/dist/helpers/dpqlDetection.d.ts.map +1 -0
- package/dist/helpers/dpqlDetection.js +164 -0
- package/dist/helpers/dpqlDetection.js.map +1 -0
- package/dist/helpers/optionUiTypes.d.ts +31 -3
- package/dist/helpers/optionUiTypes.d.ts.map +1 -1
- package/dist/helpers/optionUiTypes.js +36 -1
- package/dist/helpers/optionUiTypes.js.map +1 -1
- package/dist/helpers/options.d.ts +57 -0
- package/dist/helpers/options.d.ts.map +1 -1
- package/dist/helpers/options.js +97 -1
- package/dist/helpers/options.js.map +1 -1
- package/dist/helpers/templateItems.d.ts +47 -0
- package/dist/helpers/templateItems.d.ts.map +1 -0
- package/dist/helpers/templateItems.js +88 -0
- package/dist/helpers/templateItems.js.map +1 -0
- package/dist/helpers/templateText.d.ts +80 -0
- package/dist/helpers/templateText.d.ts.map +1 -0
- package/dist/helpers/templateText.js +291 -0
- package/dist/helpers/templateText.js.map +1 -0
- package/dist/helpers/templates.d.ts +30 -12
- package/dist/helpers/templates.d.ts.map +1 -1
- package/dist/helpers/templates.js +91 -33
- package/dist/helpers/templates.js.map +1 -1
- package/dist/helpers/validations.d.ts +35 -8
- package/dist/helpers/validations.d.ts.map +1 -1
- package/dist/helpers/validations.js +162 -25
- package/dist/helpers/validations.js.map +1 -1
- package/dist/hooks/useArgSchema.d.ts +2 -1
- package/dist/hooks/useArgSchema.d.ts.map +1 -1
- package/dist/hooks/useFetch/useFetch.d.ts +3 -1
- package/dist/hooks/useFetch/useFetch.d.ts.map +1 -1
- package/dist/hooks/useFetch/useFetch.js +47 -9
- package/dist/hooks/useFetch/useFetch.js.map +1 -1
- package/dist/hooks/useTemplates.d.ts +20 -0
- package/dist/hooks/useTemplates.d.ts.map +1 -1
- package/dist/hooks/useTemplates.js +34 -2
- package/dist/hooks/useTemplates.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/utils/fetch.d.ts +151 -1
- package/dist/utils/fetch.d.ts.map +1 -1
- package/dist/utils/fetch.js +256 -44
- package/dist/utils/fetch.js.map +1 -1
- package/dist/utils/lspClient.d.ts +6 -0
- package/dist/utils/lspClient.d.ts.map +1 -1
- package/dist/utils/lspClient.js +62 -11
- package/dist/utils/lspClient.js.map +1 -1
- package/dist/utils/websocket.d.ts +6 -0
- package/dist/utils/websocket.d.ts.map +1 -1
- package/dist/utils/websocket.js +15 -7
- package/dist/utils/websocket.js.map +1 -1
- package/package.json +10 -6
- package/src/components/composer/Composer.tsx +7 -2
- package/src/components/dpqlEditor/DpqlEditor.stories.tsx +3 -119
- package/src/components/dpqlEditor/DpqlEditor.tsx +5 -2
- package/src/components/dpqlEditor/dpqlHelpers.ts +20 -1
- package/src/components/dpqlEditor/dpqlProbe.ts +165 -0
- package/src/components/dpqlEditor/dpqlTags.ts +13 -0
- package/src/components/dpqlEditor/index.ts +4 -0
- package/src/components/dpqlEditor/types.ts +38 -2
- package/src/components/dpqlEditor/useDpqlProbe.ts +33 -0
- package/src/components/dpqlEditor/useDpqlSession.ts +20 -4
- package/src/components/form/engine/CompactRow.tsx +487 -160
- package/src/components/form/engine/CompactToolbar.tsx +10 -3
- package/src/components/form/engine/FormEngine.stories.tsx +1269 -211
- package/src/components/form/engine/FormEngine.tsx +922 -270
- package/src/components/form/engine/FormEngineStickyHeaders.stories.tsx +331 -0
- package/src/components/form/engine/FormFieldsSkeleton.tsx +77 -0
- package/src/components/form/engine/OptionFieldMessages.tsx +300 -14
- package/src/components/form/engine/_structuredData/SchemaDataView.tsx +94 -3
- package/src/components/form/engine/compactRowContext.ts +15 -6
- package/src/components/form/engine/compactRowStyles.ts +56 -2
- package/src/components/form/engine/compactToolbarContext.ts +1 -1
- package/src/components/form/engine/optionActions.ts +89 -1
- package/src/components/form/engine/optionsContext.ts +24 -0
- package/src/components/form/engine/readFirst.ts +88 -8
- package/src/components/form/engine/rendererTypes.ts +48 -4
- package/src/components/form/engine/rowFocus.ts +101 -0
- package/src/components/form/engine/rowMenuContext.ts +159 -0
- package/src/components/form/engine/rowOpenPicker.ts +27 -0
- package/src/components/form/engine/typeChoices.ts +63 -0
- package/src/components/form/expressions/DpqlRendering.tsx +85 -0
- package/src/components/form/expressions/ExpressionField.stories.tsx +826 -48
- package/src/components/form/expressions/ExpressionField.tsx +269 -55
- package/src/components/form/expressions/argumentPresence.ts +213 -0
- package/src/components/form/expressions/builder/ExpressionBuilder.stories.tsx +38 -21
- package/src/components/form/expressions/builder/argumentLabel.tsx +10 -4
- package/src/components/form/expressions/builder/index.tsx +39 -81
- package/src/components/form/expressions/builder/renderTemplate.tsx +23 -56
- package/src/components/form/expressions/dpqlMockLanguage.ts +565 -0
- package/src/components/form/expressions/dpqlMockLsp.ts +109 -83
- package/src/components/form/expressions/mockExpressions.ts +8 -4
- package/src/components/form/expressions/renderExpressionToText.ts +112 -22
- package/src/components/form/expressions/types.ts +17 -2
- package/src/components/form/expressions/useExpressions.ts +5 -1
- package/src/components/form/expressions/useRenderExpression.ts +43 -127
- package/src/components/form/fields/Field.tsx +102 -20
- package/src/components/form/fields/allowed-values/AllowedValues.tsx +106 -44
- package/src/components/form/fields/auto/AutoFormField.stories.tsx +85 -18
- package/src/components/form/fields/auto/AutoFormField.tsx +97 -21
- package/src/components/form/fields/date/Date.tsx +17 -1
- package/src/components/form/fields/long-string/LongString.tsx +15 -3
- package/src/components/form/fields/multi-select/MultiSelectFormField.tsx +65 -6
- package/src/components/form/fields/number/Number.tsx +25 -0
- package/src/components/form/fields/rich-text/RichText.tsx +248 -30
- package/src/components/form/fields/select/Select.stories.tsx +392 -0
- package/src/components/form/fields/select/Select.tsx +164 -27
- package/src/components/form/fields/select/SelectCollection.tsx +350 -6
- package/src/components/form/fields/template/ReadOnlyTemplateTag.tsx +4 -2
- package/src/components/form/fields/template/TemplateField.stories.tsx +93 -14
- package/src/components/form/fields/template/TemplateField.tsx +825 -131
- package/src/components/form/fields/template/TemplateText.tsx +115 -0
- package/src/components/form/index.tsx +4 -0
- package/src/components/log/Log.stories.tsx +2 -1
- package/src/components/searchFilterBar/SearchFilterBar.stories.tsx +3 -3
- package/src/components/smartEditor/SmartEditor.tsx +41 -9
- package/src/components/smartEditor/__fixtures__/mockLspServer.ts +52 -3
- package/src/components/smartEditor/useLspSession.ts +21 -3
- package/src/components/supportTicket/TicketReplyBox.tsx +8 -4
- package/src/components/ticketThread/TicketThread.stories.tsx +1 -0
- package/src/helpers/common.ts +7 -3
- package/src/helpers/dpqlDetection.ts +209 -0
- package/src/helpers/optionUiTypes.ts +38 -0
- package/src/helpers/options.ts +96 -0
- package/src/helpers/templateItems.ts +81 -0
- package/src/helpers/templateText.ts +350 -0
- package/src/helpers/templates.ts +94 -41
- package/src/helpers/validations.ts +203 -51
- package/src/hooks/useFetch/useFetch.stories.tsx +6 -5
- package/src/hooks/useFetch/useFetch.tsx +53 -7
- package/src/hooks/useStorage/useStorage.stories.tsx +2 -1
- package/src/hooks/useTemplates.ts +41 -0
- package/src/hooks/useWebSocket/useWebsocket.stories.tsx +2 -1
- package/src/index.tsx +14 -1
- package/src/stores/currentUser/currentUser.stories.tsx +2 -1
- package/src/stories/storyNetwork.ts +92 -0
- package/src/utils/fetch.ts +311 -21
- package/src/utils/lspClient.ts +68 -11
- package/src/utils/websocket.ts +20 -9
- package/dist/components/form/engine/__fixtures__/basicFormOptions.d.ts +0 -73
- package/dist/components/form/engine/__fixtures__/basicFormOptions.d.ts.map +0 -1
- package/dist/components/form/engine/__fixtures__/basicFormOptions.js +0 -317
- package/dist/components/form/engine/__fixtures__/basicFormOptions.js.map +0 -1
- package/dist/components/form/engine/__fixtures__/fieldChromeOptions.d.ts +0 -41
- package/dist/components/form/engine/__fixtures__/fieldChromeOptions.d.ts.map +0 -1
- package/dist/components/form/engine/__fixtures__/fieldChromeOptions.js +0 -45
- package/dist/components/form/engine/__fixtures__/fieldChromeOptions.js.map +0 -1
- package/dist/components/form/expressions/dpqlMockLsp.d.ts +0 -3
- package/dist/components/form/expressions/dpqlMockLsp.d.ts.map +0 -1
- package/dist/components/form/expressions/dpqlMockLsp.js +0 -91
- package/dist/components/form/expressions/dpqlMockLsp.js.map +0 -1
- package/dist/components/form/fields/template/__fixtures__/longExampleValue.d.ts +0 -2
- package/dist/components/form/fields/template/__fixtures__/longExampleValue.d.ts.map +0 -1
- package/dist/components/form/fields/template/__fixtures__/longExampleValue.js +0 -9
- package/dist/components/form/fields/template/__fixtures__/longExampleValue.js.map +0 -1
- package/dist/components/smartEditor/__fixtures__/mockLspServer.d.ts +0 -55
- package/dist/components/smartEditor/__fixtures__/mockLspServer.d.ts.map +0 -1
- package/dist/components/smartEditor/__fixtures__/mockLspServer.js +0 -126
- package/dist/components/smartEditor/__fixtures__/mockLspServer.js.map +0 -1
- package/dist/stories/Data/fileFieldArgSchema.json +0 -86
package/src/helpers/templates.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { modalStore } from '@qoretechnologies/reqore';
|
|
2
|
+
import { TReqoreTooltipProp } from '@qoretechnologies/reqore/dist/types/global';
|
|
2
3
|
import { IReqoreFormTemplates } from '@qoretechnologies/reqore/dist/components/Textarea';
|
|
3
4
|
import {
|
|
4
5
|
TReqoreDropdownItem,
|
|
@@ -20,6 +21,24 @@ import { areQorusTypesCompatible } from './expressions';
|
|
|
20
21
|
*/
|
|
21
22
|
export const TEMPLATE_EXAMPLE_PREVIEW_LENGTH = 150;
|
|
22
23
|
|
|
24
|
+
/**
|
|
25
|
+
* How template picker entries are ordered: by the label a reader actually sees.
|
|
26
|
+
*
|
|
27
|
+
* The server sends groups and their items in whatever order it assembled them —
|
|
28
|
+
* for the test vocabulary that is step order, for an app's actions it is the
|
|
29
|
+
* connector's own. Neither is an order a reader can predict, and a picker
|
|
30
|
+
* holding 29 items is navigated by looking for a NAME.
|
|
31
|
+
*
|
|
32
|
+
* `localeCompare` with `numeric` so `item2` sorts before `item10`, and
|
|
33
|
+
* `sensitivity: 'base'` so case and accents do not split otherwise-adjacent
|
|
34
|
+
* neighbours.
|
|
35
|
+
*/
|
|
36
|
+
const byLabel = (a: { label?: unknown }, b: { label?: unknown }): number =>
|
|
37
|
+
String(a?.label ?? '').localeCompare(String(b?.label ?? ''), undefined, {
|
|
38
|
+
numeric: true,
|
|
39
|
+
sensitivity: 'base',
|
|
40
|
+
});
|
|
41
|
+
|
|
23
42
|
/**
|
|
24
43
|
* Shared template string utilities.
|
|
25
44
|
* Used by both validations and TemplateField.
|
|
@@ -106,9 +125,42 @@ const matchesTemplateValue = (item: TReqoreDropdownItem, value: string): boolean
|
|
|
106
125
|
/** Splits `$data:{a.b.c}` into its key (`$data`) and inner path (`a.b.c`). */
|
|
107
126
|
const TEMPLATE_TOKEN_PATH = /^(\$[A-Za-z_][\w-]*):\{(.*)\}$/;
|
|
108
127
|
|
|
128
|
+
/**
|
|
129
|
+
* The KEY-LESS spelling — `$.create.status`, `$._case.mode`, `$.order[0].sku`.
|
|
130
|
+
*
|
|
131
|
+
* A host may name its own references without a key and without braces: a Qorus
|
|
132
|
+
* test reads what a step captured as `$.create`, and that is the whole token.
|
|
133
|
+
* The path is captured WITH its leading `.`, so a prefix comparison is between
|
|
134
|
+
* two strings of the same shape and `$.create` still ends at a path boundary
|
|
135
|
+
* inside `$.create.status`.
|
|
136
|
+
*
|
|
137
|
+
* Deliberately strict — a root segment, then any number of further `.field`
|
|
138
|
+
* steps and `[0]` indices, and nothing else — so it cannot claim a keyed token
|
|
139
|
+
* (which carries a `:`) or a bare `$word`.
|
|
140
|
+
*/
|
|
141
|
+
const KEYLESS_TOKEN_PATH = /^\$((?:\.[A-Za-z_][\w-]*|\[\d+\])+)$/;
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* "No key" is a key of its own.
|
|
145
|
+
*
|
|
146
|
+
* `findTemplateByPath` refuses to name a value from an item under a different
|
|
147
|
+
* key, and the key-less grammar has to take part in that rule rather than sit
|
|
148
|
+
* outside it: a `$data:{create.status}` item must not name `$.create.status`,
|
|
149
|
+
* and a `$.create` item must not name `$data:{create.status}`. Every keyed
|
|
150
|
+
* token's key begins with `$`, so the empty string can never collide with one.
|
|
151
|
+
*/
|
|
152
|
+
const NO_TOKEN_KEY = '';
|
|
153
|
+
|
|
109
154
|
const getTokenPath = (value?: unknown): { key: string; path: string } | undefined => {
|
|
110
|
-
|
|
111
|
-
|
|
155
|
+
if (typeof value !== 'string') {
|
|
156
|
+
return undefined;
|
|
157
|
+
}
|
|
158
|
+
const keyed = TEMPLATE_TOKEN_PATH.exec(value);
|
|
159
|
+
if (keyed) {
|
|
160
|
+
return { key: keyed[1], path: keyed[2] };
|
|
161
|
+
}
|
|
162
|
+
const keyless = KEYLESS_TOKEN_PATH.exec(value);
|
|
163
|
+
return keyless ? { key: NO_TOKEN_KEY, path: keyless[1] } : undefined;
|
|
112
164
|
};
|
|
113
165
|
|
|
114
166
|
/**
|
|
@@ -124,7 +176,12 @@ const getTokenPath = (value?: unknown): { key: string; path: string } | undefine
|
|
|
124
176
|
*
|
|
125
177
|
* The match must break at a path boundary (`.` or `[`) so `choicesOther` is
|
|
126
178
|
* never named after `choices`, and the token keys must agree so a `$config:`
|
|
127
|
-
* item never names a `$data:` value
|
|
179
|
+
* item never names a `$data:` value — "no key" included, so the key-less
|
|
180
|
+
* grammar and the keyed one never name each other's references.
|
|
181
|
+
*
|
|
182
|
+
* Both grammars arrive here: `$data:{create.choices[0]}` and the key-less
|
|
183
|
+
* `$.create.status` are the same question asked in two spellings, and a
|
|
184
|
+
* catalogue written in either one names the walks its author took past it.
|
|
128
185
|
*/
|
|
129
186
|
export const findTemplateByPath = (
|
|
130
187
|
templates: IReqoreFormTemplates,
|
|
@@ -239,9 +296,14 @@ export const resolveTemplateLabel = (
|
|
|
239
296
|
* never fetches one), and there the raw token is the only thing left to show.
|
|
240
297
|
* Showing it as `$data:{…}` renders a value as code; showing the path renders
|
|
241
298
|
* it as a name, which is the honest floor.
|
|
299
|
+
*
|
|
300
|
+
* Only a BRACED wrapper is stripped, because only a braced wrapper is one.
|
|
301
|
+
* A key-less `$._case.mode` stripped of its `$` reads as `._case.mode`, which
|
|
302
|
+
* is neither the reference nor a name for it; with nothing to call it, the
|
|
303
|
+
* reference as written is the honest answer.
|
|
242
304
|
*/
|
|
243
305
|
export const getTemplateReferencePath = (value: string): string =>
|
|
244
|
-
|
|
306
|
+
(typeof value === 'string' ? TEMPLATE_TOKEN_PATH.exec(value)?.[2] : undefined) ?? value;
|
|
245
307
|
|
|
246
308
|
/**
|
|
247
309
|
* The best available name for a reference, for a surface that must show
|
|
@@ -258,43 +320,34 @@ export const describeTemplateReference = (
|
|
|
258
320
|
return resolved.item ? resolved : { label: getTemplateReferencePath(value) };
|
|
259
321
|
};
|
|
260
322
|
|
|
261
|
-
const EMBEDDED_TEMPLATE_TOKEN = new RegExp(TEMPLATE_TOKEN_SOURCE, 'g');
|
|
262
|
-
|
|
263
|
-
export type TTemplateTextSegment =
|
|
264
|
-
| { kind: 'text'; text: string }
|
|
265
|
-
| { kind: 'token'; text: string };
|
|
266
|
-
|
|
267
323
|
/**
|
|
268
|
-
*
|
|
269
|
-
*
|
|
270
|
-
*
|
|
324
|
+
* What a chosen template's hover should say.
|
|
325
|
+
*
|
|
326
|
+
* The reference itself — `$._case.title`, `$data:{dc_ai_reply.choices[0]…}` —
|
|
327
|
+
* is an implementation detail of the grammar, and it was what every template
|
|
328
|
+
* chip put in its tooltip. An author hovering a chip wants to know WHAT VALUE
|
|
329
|
+
* this is, and the catalogue already carries that: the entry's `description`
|
|
330
|
+
* is the prose the picker lists it under, written from the schema that declares
|
|
331
|
+
* it, with its type appended.
|
|
332
|
+
*
|
|
333
|
+
* So the hover reads as a small card — the value's name as the title, its
|
|
334
|
+
* description as the body — and the path stays where it is genuinely needed:
|
|
335
|
+
* the field's own help, which teaches the grammar with a worked example, and
|
|
336
|
+
* the picker, for the walks no list can hold.
|
|
337
|
+
*
|
|
338
|
+
* Falls back to the resolved label (itself the stripped path when the catalogue
|
|
339
|
+
* explains nothing), because a surface with no catalogue must still say what
|
|
340
|
+
* the value is rather than nothing at all.
|
|
271
341
|
*/
|
|
272
|
-
export const
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
const
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
// calls and would skip tokens on the second string it is given.
|
|
282
|
-
const pattern = new RegExp(EMBEDDED_TEMPLATE_TOKEN.source, 'g');
|
|
283
|
-
let match: RegExpExecArray | null;
|
|
284
|
-
|
|
285
|
-
while ((match = pattern.exec(text)) !== null) {
|
|
286
|
-
if (match.index > lastIndex) {
|
|
287
|
-
segments.push({ kind: 'text', text: text.slice(lastIndex, match.index) });
|
|
288
|
-
}
|
|
289
|
-
segments.push({ kind: 'token', text: match[0] });
|
|
290
|
-
lastIndex = match.index + match[0].length;
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
if (lastIndex < text.length) {
|
|
294
|
-
segments.push({ kind: 'text', text: text.slice(lastIndex) });
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
return segments;
|
|
342
|
+
export const templateTooltip = (
|
|
343
|
+
templates: IReqoreFormTemplates | undefined,
|
|
344
|
+
value: string
|
|
345
|
+
): TReqoreTooltipProp => {
|
|
346
|
+
const { label, item } = describeTemplateReference(templates, value);
|
|
347
|
+
const description = (item as { description?: unknown } | undefined)?.description;
|
|
348
|
+
return typeof description === 'string' && description.trim() ?
|
|
349
|
+
{ title: label, content: description, maxWidth: '360px' }
|
|
350
|
+
: label || value;
|
|
298
351
|
};
|
|
299
352
|
|
|
300
353
|
// Ported verbatim from qorus-ide `helpers/functions.tsx` (FIELD_STACK_REPORT
|
|
@@ -506,7 +559,7 @@ export const buildTemplates = (
|
|
|
506
559
|
|
|
507
560
|
return item;
|
|
508
561
|
}
|
|
509
|
-
);
|
|
562
|
+
).sort(byLabel);
|
|
510
563
|
|
|
511
564
|
return {
|
|
512
565
|
items: Object.values(templates).map(
|
|
@@ -544,6 +597,6 @@ export const buildTemplates = (
|
|
|
544
597
|
data_role
|
|
545
598
|
),
|
|
546
599
|
})
|
|
547
|
-
),
|
|
600
|
+
).sort(byLabel),
|
|
548
601
|
} as IReqoreFormTemplates;
|
|
549
602
|
};
|
|
@@ -75,6 +75,24 @@ interface IFieldValidationProps {
|
|
|
75
75
|
* mapped onto the corresponding `has_to_be_*` flags. */
|
|
76
76
|
rules?: string[];
|
|
77
77
|
validation_regex?: string;
|
|
78
|
+
/**
|
|
79
|
+
* The inclusive bounds a numeric field accepts — read only by the `int`, `float`
|
|
80
|
+
* and `number` validators.
|
|
81
|
+
*
|
|
82
|
+
* Declared here rather than imported because ts-toolkit still does not carry them:
|
|
83
|
+
* 0.5.82 added the allowed-value and message members reqraft was waiting on, but
|
|
84
|
+
* `IQorusFormFieldSchemaBase` has no numeric bound. These two collapse into the
|
|
85
|
+
* imported type once it does — unlike the allowed-value shapes, which stay local
|
|
86
|
+
* for a reason of their own.
|
|
87
|
+
*
|
|
88
|
+
* The server declares a bound only where that same bound is already enforced on the
|
|
89
|
+
* write (`MetaFieldInfo::min_value`), so refusing a value here turns an error the
|
|
90
|
+
* author would otherwise meet on save into one they meet while the field is still on
|
|
91
|
+
* screen. It never enforces the bound, and it never refuses a value the server would
|
|
92
|
+
* have accepted.
|
|
93
|
+
*/
|
|
94
|
+
min_value?: number;
|
|
95
|
+
max_value?: number;
|
|
78
96
|
required_groups?: string[];
|
|
79
97
|
optionSchema?: IQorusFormSchema;
|
|
80
98
|
/** The sibling option VALUES, for required-group and dependency checks.
|
|
@@ -174,6 +192,41 @@ const withContext = (result: IValidationResult, context?: string): IValidationRe
|
|
|
174
192
|
const resultFromBoolean = (isValid: boolean, reason: string): IValidationResult =>
|
|
175
193
|
isValid ? validResult() : invalidResult(reason);
|
|
176
194
|
|
|
195
|
+
/**
|
|
196
|
+
* Whether the value is a number at all — the check the `number` and `float` cases both
|
|
197
|
+
* make before any bound is read. Shared because the two differ only in the wording of
|
|
198
|
+
* the refusal, and a predicate that drifted between them would leave one of the pair
|
|
199
|
+
* accepting what the other refuses.
|
|
200
|
+
*/
|
|
201
|
+
const isNumericValue = (value: any): boolean =>
|
|
202
|
+
!isNaN(value) && (getTypeFromValue(value) === 'float' || getTypeFromValue(value) === 'int');
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* The schema-declared range for a value that is already the right kind of number.
|
|
206
|
+
*
|
|
207
|
+
* Both bounds are inclusive and either may stand alone — the server declares only the
|
|
208
|
+
* side it can point at an enforcing line for, so a count with a floor and no ceiling
|
|
209
|
+
* arrives with `min_value` alone. A bound that is not a finite number is ignored rather
|
|
210
|
+
* than treated as zero: a schema that says nothing must not refuse everything.
|
|
211
|
+
*
|
|
212
|
+
* Kept out of the type checks above it so the reason a value is refused says which
|
|
213
|
+
* thing is wrong — "must be a whole number" and "must be at least 1" are different
|
|
214
|
+
* corrections, and collapsing them into one message makes the author guess.
|
|
215
|
+
*/
|
|
216
|
+
const checkNumericBounds = (value: any, field?: IFieldValidationProps): IValidationResult => {
|
|
217
|
+
const num = Number(value);
|
|
218
|
+
const min = field?.min_value;
|
|
219
|
+
const max = field?.max_value;
|
|
220
|
+
|
|
221
|
+
if (typeof min === 'number' && Number.isFinite(min) && num < min) {
|
|
222
|
+
return invalidResult(`Value must be ${min} or more`);
|
|
223
|
+
}
|
|
224
|
+
if (typeof max === 'number' && Number.isFinite(max) && num > max) {
|
|
225
|
+
return invalidResult(`Value must be ${max} or less`);
|
|
226
|
+
}
|
|
227
|
+
return validResult();
|
|
228
|
+
};
|
|
229
|
+
|
|
177
230
|
const isRichTextWithoutValue = (value: any): boolean => {
|
|
178
231
|
return (
|
|
179
232
|
value === undefined ||
|
|
@@ -574,21 +627,21 @@ export const _validateField = (
|
|
|
574
627
|
return valid ? validResult() : invalidResult(undefined, reasons);
|
|
575
628
|
}
|
|
576
629
|
case 'number': {
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
);
|
|
630
|
+
if (!isNumericValue(value)) {
|
|
631
|
+
return invalidResult('Value must be a number');
|
|
632
|
+
}
|
|
633
|
+
return checkNumericBounds(value, field);
|
|
581
634
|
}
|
|
582
635
|
case 'int':
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
);
|
|
636
|
+
if (!(!Number.isNaN(value) && getTypeFromValue(value) === 'int')) {
|
|
637
|
+
return invalidResult('Value must be an integer');
|
|
638
|
+
}
|
|
639
|
+
return checkNumericBounds(value, field);
|
|
587
640
|
case 'float':
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
);
|
|
641
|
+
if (!isNumericValue(value)) {
|
|
642
|
+
return invalidResult('Value must be a float');
|
|
643
|
+
}
|
|
644
|
+
return checkNumericBounds(value, field);
|
|
592
645
|
case 'select-array':
|
|
593
646
|
case 'multi-select':
|
|
594
647
|
case 'array':
|
|
@@ -1064,14 +1117,39 @@ export const _validateField = (
|
|
|
1064
1117
|
}
|
|
1065
1118
|
}
|
|
1066
1119
|
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1120
|
+
/* A FALSY value is not an ABSENT one. `null`, `0`, `false` and `""` are
|
|
1121
|
+
all values an author may hold in an `auto`/`any` field — a test
|
|
1122
|
+
assertion expecting a count of zero, a flag that is off, or a blank
|
|
1123
|
+
string — and the truthiness gate that used to stand here refused every
|
|
1124
|
+
one of them as *"Value is empty"*. It surfaced on an assertion's
|
|
1125
|
+
Expected Value holding `null`: opening it reported *"Value for argument
|
|
1126
|
+
1 ("any") is invalid: Value is empty"* on the value the author had
|
|
1127
|
+
deliberately chosen. Only `undefined` is actually empty.
|
|
1128
|
+
|
|
1129
|
+
`null` and `""` are answered here rather than delegated, for two
|
|
1130
|
+
different reasons: `getTypeFromValue(null)` answers `auto`, which would
|
|
1131
|
+
re-enter this very branch, and the `string` validator rejects `""`
|
|
1132
|
+
because that is the rule for a REQUIRED text field — a different
|
|
1133
|
+
question from whether an untyped field may hold a blank string. */
|
|
1134
|
+
if (parsedData === undefined) {
|
|
1135
|
+
return invalidResult('Value is empty');
|
|
1072
1136
|
}
|
|
1073
1137
|
|
|
1074
|
-
|
|
1138
|
+
if (parsedData === null || parsedData === '') {
|
|
1139
|
+
return validResult();
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
/* Validate what was PARSED, against the type detected from the same
|
|
1143
|
+
parse. Validating the raw `value` instead made the two disagree
|
|
1144
|
+
whenever parsing changed the shape: typing `1` into an `auto` field
|
|
1145
|
+
parsed to the number 1, detected `int`, and then validated the STRING
|
|
1146
|
+
"1" against it — "Value must be an integer", on a value that is one.
|
|
1147
|
+
The author saw their field go invalid on the first character they
|
|
1148
|
+
typed. */
|
|
1149
|
+
return withContext(
|
|
1150
|
+
validateFieldWithResult(getTypeFromValue(parsedData), parsedData),
|
|
1151
|
+
'Auto-detected type is invalid'
|
|
1152
|
+
);
|
|
1075
1153
|
}
|
|
1076
1154
|
case 'processor': {
|
|
1077
1155
|
if (!value || !value['processor-input-type'] || !value['processor-output-type']) {
|
|
@@ -1295,6 +1373,22 @@ export const _validateField = (
|
|
|
1295
1373
|
continue;
|
|
1296
1374
|
}
|
|
1297
1375
|
|
|
1376
|
+
/* An option whose dependencies are not fulfilled is not part of this
|
|
1377
|
+
object, so it cannot make the object invalid.
|
|
1378
|
+
|
|
1379
|
+
The form already takes that view — it HIDES such an option — and
|
|
1380
|
+
the two disagreeing is a trap with no way out of it: a test whose
|
|
1381
|
+
subject moved from a versioned kind to a service keeps the
|
|
1382
|
+
`subject_iface_version` it no longer has a field for, and Submit
|
|
1383
|
+
goes dead naming an option that is nowhere on screen. Nulling the
|
|
1384
|
+
value does not help either, because a null is still a value the
|
|
1385
|
+
loop reaches.
|
|
1386
|
+
|
|
1387
|
+
A REQUIRED option with unfulfilled dependencies is unaffected:
|
|
1388
|
+
`getUnresolvedRequiredOptions` above reports it as `dependency`
|
|
1389
|
+
before this loop runs, and it is the only owner of that question.
|
|
1390
|
+
This branch was therefore only ever able to fail an option the
|
|
1391
|
+
author could not see and did not need. */
|
|
1298
1392
|
if (
|
|
1299
1393
|
(optionSchema?.[option] as TQorusFormFieldSchema)?.depends_on &&
|
|
1300
1394
|
!hasAllDependenciesFullfilled(
|
|
@@ -1303,7 +1397,7 @@ export const _validateField = (
|
|
|
1303
1397
|
optionSchema
|
|
1304
1398
|
)
|
|
1305
1399
|
) {
|
|
1306
|
-
|
|
1400
|
+
continue;
|
|
1307
1401
|
}
|
|
1308
1402
|
|
|
1309
1403
|
const optionResult =
|
|
@@ -1512,6 +1606,31 @@ export const _validateField = (
|
|
|
1512
1606
|
const argDefinition = expressionDefinition.varargs
|
|
1513
1607
|
? expressionDefinition.args[0]
|
|
1514
1608
|
: expressionDefinition.args[index];
|
|
1609
|
+
/* The argument's name for the message.
|
|
1610
|
+
|
|
1611
|
+
`display_name` is what a catalogue MAY carry; the served one carries
|
|
1612
|
+
`name`, so every message about an argument read "argument 1
|
|
1613
|
+
("undefined") is invalid" and named a field that does not exist. */
|
|
1614
|
+
const argLabel =
|
|
1615
|
+
argDefinition?.display_name ?? argDefinition?.name ?? `argument ${index + 1}`;
|
|
1616
|
+
|
|
1617
|
+
/* An explicit null is a VALUE, and DPQL says so: `null` is a literal
|
|
1618
|
+
that parses, serializes and round-trips like any other.
|
|
1619
|
+
|
|
1620
|
+
Treated as a missing one, it made "this returns no value"
|
|
1621
|
+
unsayable. Typing `null` into the text editor produces the literal
|
|
1622
|
+
expression `{exp: "value", args: [null]}`; the visual view then
|
|
1623
|
+
called it invalid and refused to render a summary, and a raw null
|
|
1624
|
+
argument crashed the validator outright on `argValue.type`. Reported
|
|
1625
|
+
from the live IDE by an author with no other way to assert that a
|
|
1626
|
+
service method returns nothing.
|
|
1627
|
+
|
|
1628
|
+
Only an EXPLICIT null counts. An argument that is simply absent, or
|
|
1629
|
+
an envelope holding `undefined`, is still missing — which is the
|
|
1630
|
+
distinction the author is making when they write it. */
|
|
1631
|
+
if (argValue === null || (isObject(argValue) && (argValue as any).value === null)) {
|
|
1632
|
+
continue;
|
|
1633
|
+
}
|
|
1515
1634
|
|
|
1516
1635
|
if (!argValue?.value && !argDefinition?.required) {
|
|
1517
1636
|
continue;
|
|
@@ -1526,30 +1645,34 @@ export const _validateField = (
|
|
|
1526
1645
|
if (!result.isValid) {
|
|
1527
1646
|
return withContext(
|
|
1528
1647
|
result,
|
|
1529
|
-
`Sub-expression for argument ${index + 1} ("${
|
|
1648
|
+
`Sub-expression for argument ${index + 1} ("${argLabel}") is invalid`
|
|
1530
1649
|
);
|
|
1531
1650
|
}
|
|
1532
1651
|
|
|
1533
1652
|
continue;
|
|
1534
1653
|
}
|
|
1535
1654
|
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1655
|
+
/* A slot with no operand at all is judged as what it is — a missing
|
|
1656
|
+
value — rather than read for a `type` it does not have.
|
|
1657
|
+
|
|
1658
|
+
An operand that HOLDS something is judged by the envelope's own type,
|
|
1659
|
+
or — when the envelope carries none (a raw parse operand widened
|
|
1660
|
+
without a `ui_type`, a slot reset by a type change) — by the type the
|
|
1661
|
+
catalogue declares. Without that fallback `_validateField` refuses it
|
|
1662
|
+
for "Missing type" however right the value is. */
|
|
1663
|
+
const operandType =
|
|
1664
|
+
argValue?.type ?? (argValue?.value === undefined ? undefined : argDefinition?.ui_type);
|
|
1665
|
+
const result = validateFieldWithResult(operandType, argValue?.value, {
|
|
1666
|
+
expressions,
|
|
1667
|
+
allowed_values: argDefinition?.allowed_values,
|
|
1668
|
+
element_allowed_values: argDefinition?.element_allowed_values,
|
|
1669
|
+
has_to_have_value: argDefinition?.required,
|
|
1670
|
+
});
|
|
1548
1671
|
|
|
1549
1672
|
if (!result.isValid) {
|
|
1550
1673
|
return withContext(
|
|
1551
1674
|
result,
|
|
1552
|
-
`Value for argument ${index + 1} ("${
|
|
1675
|
+
`Value for argument ${index + 1} ("${argLabel}") is invalid`
|
|
1553
1676
|
);
|
|
1554
1677
|
}
|
|
1555
1678
|
}
|
|
@@ -1818,19 +1941,28 @@ export const getUnresolvedRequiredOptions = (
|
|
|
1818
1941
|
/**
|
|
1819
1942
|
* Split a dependency entry into the sibling it names and how its value is compared.
|
|
1820
1943
|
*
|
|
1821
|
-
*
|
|
1822
|
-
* have exactly that value) and `name!=value` (it must
|
|
1823
|
-
* one). The negative
|
|
1824
|
-
* record but one — spelling that as an `any-of`
|
|
1825
|
-
* unreadable in the "Depends on" lock and
|
|
1826
|
-
* added.
|
|
1944
|
+
* Four forms: `name` (the sibling must simply have a value), `!name` (it must have
|
|
1945
|
+
* none), `name=value` (it must have exactly that value) and `name!=value` (it must
|
|
1946
|
+
* have a value, and not that one). The negative comparison is what lets a field say
|
|
1947
|
+
* it applies to every variant of a record but one — spelling that as an `any-of`
|
|
1948
|
+
* list of every other variant is both unreadable in the "Depends on" lock and
|
|
1949
|
+
* silently wrong the moment a variant is added.
|
|
1827
1950
|
*
|
|
1828
1951
|
* `!=` deliberately requires the sibling to be answered: "not X" is a statement about
|
|
1829
1952
|
* an answer, so an unanswered sibling does not satisfy it and the field stays locked.
|
|
1953
|
+
*
|
|
1954
|
+
* `!name` is the form that statement cannot make. Two options that exclude one
|
|
1955
|
+
* another (a converter that reads NodeSet2 and one that writes OpenAPI 3) each
|
|
1956
|
+
* apply only while the OTHER has not been answered at all, and `name!=value` cannot
|
|
1957
|
+
* say that: it requires an answer. Being a predicate like any other, it composes
|
|
1958
|
+
* with the AND of the top-level entries and the OR of a nested list for free.
|
|
1959
|
+
*
|
|
1960
|
+
* `!` binds to the whole entry, so `!name` never carries a value; `!=` is checked
|
|
1961
|
+
* first, which is what keeps `name!=value` from being read as a leading `!`.
|
|
1830
1962
|
*/
|
|
1831
1963
|
export const parseDependency = (
|
|
1832
1964
|
dependency: string
|
|
1833
|
-
): { name: string; op?: '=' | '!='; value?: string } => {
|
|
1965
|
+
): { name: string; op?: '=' | '!=' | '!'; value?: string } => {
|
|
1834
1966
|
const neqIdx = dependency.indexOf('!=');
|
|
1835
1967
|
if (neqIdx !== -1) {
|
|
1836
1968
|
return {
|
|
@@ -1849,9 +1981,25 @@ export const parseDependency = (
|
|
|
1849
1981
|
};
|
|
1850
1982
|
}
|
|
1851
1983
|
|
|
1984
|
+
if (dependency.startsWith('!')) {
|
|
1985
|
+
return { name: dependency.substring(1), op: '!' };
|
|
1986
|
+
}
|
|
1987
|
+
|
|
1852
1988
|
return { name: dependency };
|
|
1853
1989
|
};
|
|
1854
1990
|
|
|
1991
|
+
/** Whether the named sibling currently holds a value this form accepts. */
|
|
1992
|
+
const siblingHasValue = (
|
|
1993
|
+
name: string,
|
|
1994
|
+
options: TQorusForm,
|
|
1995
|
+
optionsSchema?: IQorusFormSchema
|
|
1996
|
+
): boolean =>
|
|
1997
|
+
validateField(options?.[name]?.type, options?.[name]?.value, {
|
|
1998
|
+
...(optionsSchema?.[name] as unknown as IFieldValidationProps),
|
|
1999
|
+
options,
|
|
2000
|
+
optionSchema: optionsSchema,
|
|
2001
|
+
});
|
|
2002
|
+
|
|
1855
2003
|
/** Whether one dependency entry holds against the current form values. */
|
|
1856
2004
|
const isDependencyFulfilled = (
|
|
1857
2005
|
dependency: string,
|
|
@@ -1860,6 +2008,15 @@ const isDependencyFulfilled = (
|
|
|
1860
2008
|
): boolean => {
|
|
1861
2009
|
const { name, op, value } = parseDependency(dependency);
|
|
1862
2010
|
|
|
2011
|
+
if (op === '!') {
|
|
2012
|
+
// "Has no value" is true of a field the form has not materialized at all —
|
|
2013
|
+
// there is nothing there to be the value. So an absent sibling satisfies
|
|
2014
|
+
// this, exactly as it satisfies the bare form below: neither has an answer
|
|
2015
|
+
// to judge, and a mutual exclusion that locked both halves until one of
|
|
2016
|
+
// them was added would offer the author no way in.
|
|
2017
|
+
return !options?.[name] || !siblingHasValue(name, options, optionsSchema);
|
|
2018
|
+
}
|
|
2019
|
+
|
|
1863
2020
|
if (op) {
|
|
1864
2021
|
const optValue = options?.[name]?.value;
|
|
1865
2022
|
if (optValue == null) {
|
|
@@ -1868,17 +2025,12 @@ const isDependencyFulfilled = (
|
|
|
1868
2025
|
return op === '=' ? String(optValue) === value : String(optValue) !== value;
|
|
1869
2026
|
}
|
|
1870
2027
|
|
|
1871
|
-
return options?.[name]
|
|
1872
|
-
? validateField(options[name].type, options[name].value, {
|
|
1873
|
-
...(optionsSchema?.[name] as unknown as IFieldValidationProps),
|
|
1874
|
-
options,
|
|
1875
|
-
optionSchema: optionsSchema,
|
|
1876
|
-
})
|
|
1877
|
-
: true;
|
|
2028
|
+
return options?.[name] ? siblingHasValue(name, options, optionsSchema) : true;
|
|
1878
2029
|
};
|
|
1879
2030
|
|
|
1880
2031
|
export const hasAllDependenciesFullfilled = (
|
|
1881
|
-
|
|
2032
|
+
/** Every entry must hold; a nested list is an ANY of its entries. Mixed freely. */
|
|
2033
|
+
dependencies: ReadonlyArray<string | readonly string[]>,
|
|
1882
2034
|
options: TQorusForm,
|
|
1883
2035
|
optionsSchema?: IQorusFormSchema
|
|
1884
2036
|
): boolean => {
|
|
@@ -1886,20 +2038,20 @@ export const hasAllDependenciesFullfilled = (
|
|
|
1886
2038
|
return true;
|
|
1887
2039
|
}
|
|
1888
2040
|
|
|
1889
|
-
return dependencies.every((dependency
|
|
2041
|
+
return dependencies.every((dependency) => {
|
|
1890
2042
|
// A nested list is an ANY. It used to look each entry up as a whole form-field
|
|
1891
2043
|
// name, so a `name=value` entry inside one found no field and returned `true`
|
|
1892
2044
|
// unconditionally — the any-of group was satisfied by anything at all, while
|
|
1893
2045
|
// CompactRow's lock rendered those same entries as real comparisons. Both halves
|
|
1894
2046
|
// now go through one parser, so the grammar cannot mean two things.
|
|
1895
2047
|
if (isArray(dependency)) {
|
|
1896
|
-
return (dependency as string[]).some((dep) =>
|
|
2048
|
+
return (dependency as readonly string[]).some((dep) =>
|
|
1897
2049
|
isDependencyFulfilled(dep, options, optionsSchema)
|
|
1898
2050
|
);
|
|
1899
2051
|
}
|
|
1900
2052
|
|
|
1901
2053
|
return isString(dependency)
|
|
1902
|
-
? isDependencyFulfilled(dependency
|
|
2054
|
+
? isDependencyFulfilled(dependency, options, optionsSchema)
|
|
1903
2055
|
: true;
|
|
1904
2056
|
});
|
|
1905
2057
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ReqoreSpinner, ReqoreTree } from '@qoretechnologies/reqore';
|
|
2
2
|
import { StoryObj } from '@storybook/react-vite';
|
|
3
3
|
import { testsWaitForText } from '../../../__tests__/utils';
|
|
4
|
+
import { storyApiUrl } from '../../stories/storyNetwork';
|
|
4
5
|
import { StoryMeta } from '../../types';
|
|
5
6
|
import { useFetch } from './useFetch';
|
|
6
7
|
|
|
@@ -44,7 +45,7 @@ export const Get: Story = {
|
|
|
44
45
|
mockData: [
|
|
45
46
|
{
|
|
46
47
|
// An array of mock objects which will add in every story
|
|
47
|
-
url: '
|
|
48
|
+
url: storyApiUrl('public/info'),
|
|
48
49
|
method: 'GET',
|
|
49
50
|
status: 200,
|
|
50
51
|
delay: 200,
|
|
@@ -81,7 +82,7 @@ export const Put: Story = {
|
|
|
81
82
|
mockData: [
|
|
82
83
|
{
|
|
83
84
|
// An array of mock objects which will add in every story
|
|
84
|
-
url: '
|
|
85
|
+
url: storyApiUrl('public/info'),
|
|
85
86
|
method: 'PUT',
|
|
86
87
|
status: 200,
|
|
87
88
|
response: {
|
|
@@ -109,7 +110,7 @@ export const Post: Story = {
|
|
|
109
110
|
mockData: [
|
|
110
111
|
{
|
|
111
112
|
// An array of mock objects which will add in every story
|
|
112
|
-
url: '
|
|
113
|
+
url: storyApiUrl('public/info'),
|
|
113
114
|
method: 'POST',
|
|
114
115
|
status: 200,
|
|
115
116
|
response: {
|
|
@@ -137,7 +138,7 @@ export const Del: Story = {
|
|
|
137
138
|
mockData: [
|
|
138
139
|
{
|
|
139
140
|
// An array of mock objects which will add in every story
|
|
140
|
-
url: '
|
|
141
|
+
url: storyApiUrl('public/info'),
|
|
141
142
|
method: 'DELETE',
|
|
142
143
|
status: 200,
|
|
143
144
|
response: {
|
|
@@ -165,7 +166,7 @@ export const Error409: Story = {
|
|
|
165
166
|
mockData: [
|
|
166
167
|
{
|
|
167
168
|
// An array of mock objects which will add in every story
|
|
168
|
-
url: '
|
|
169
|
+
url: storyApiUrl('public/info'),
|
|
169
170
|
method: 'POST',
|
|
170
171
|
status: 409,
|
|
171
172
|
response: {
|