From 46d9381905de4a28d759795f5501a3a8da479087 Mon Sep 17 00:00:00 2001 From: TheNoxium Date: Mon, 6 Oct 2025 19:13:55 +0500 Subject: [PATCH] feat: pydantic descriptors --- core/__init__.py | 4 +- core/form_descriptors.py | 460 ------------------ core/vork_node_start.py | 63 --- core/vork_node_test.py | 49 ++ model_nodes/__init__.py | 22 +- model_nodes/form_base_descriptor_models.py | 75 +++ model_nodes/node_callback_models.py | 81 +++ model_nodes/node_each_models.py | 28 ++ model_nodes/node_if_models.py | 28 ++ model_nodes/node_listen_models.py | 40 ++ model_nodes/node_run_models.py | 41 ++ model_nodes/node_set_models.py | 41 ++ model_nodes/node_switch_models.py | 28 ++ ...de_start_models.py => node_test_models.py} | 22 +- model_nodes/node_trigger_models.py | 40 ++ model_nodes/node_wait_models.py | 54 ++ model_nodes/node_while_models.py | 28 ++ nodes/vork_node_callback.py | 8 +- nodes/vork_node_each.py | 6 +- nodes/vork_node_if.py | 6 +- nodes/vork_node_listen.py | 6 +- nodes/vork_node_run.py | 7 +- nodes/vork_node_set.py | 6 +- nodes/vork_node_switch.py | 6 +- nodes/vork_node_trigger.py | 6 +- nodes/vork_node_wait.py | 6 +- nodes/vork_node_while.py | 6 +- poetry.lock | 4 +- 28 files changed, 589 insertions(+), 582 deletions(-) delete mode 100644 core/form_descriptors.py delete mode 100644 core/vork_node_start.py create mode 100644 core/vork_node_test.py create mode 100644 model_nodes/form_base_descriptor_models.py rename model_nodes/{node_start_models.py => node_test_models.py} (60%) diff --git a/core/__init__.py b/core/__init__.py index 073ab2e..0e9b91a 100644 --- a/core/__init__.py +++ b/core/__init__.py @@ -1,7 +1,7 @@ from .vork_node import VorkNode from .vork_node_registry import VorkNodeRegistry from .vork_node_link import VorkNodeLink -from .vork_node_start import VorkNodeStart +from .vork_node_test import VorkNodeTest from .link_name_generator import edge_title_generator, edge_title_to_number __version__ = "0.1.0" @@ -11,7 +11,7 @@ __all__ = [ "VorkNode", "VorkNodeRegistry", "VorkNodeLink", - "VorkNodeStart", + "VorkNodeTest", "edge_title_generator", "edge_title_to_number", ] diff --git a/core/form_descriptors.py b/core/form_descriptors.py deleted file mode 100644 index 40fe5bc..0000000 --- a/core/form_descriptors.py +++ /dev/null @@ -1,460 +0,0 @@ -from typing import Dict, Any - -# Дескриптор формы для узла IF -IF_FORM_DESCRIPTOR = { - "elements": [ - { - "name": "condition_row", - "type": "row", - "label": "Условие проверки", - "link_port": { - "id": "then_output", - "label": "Then" - }, - "elements": [ - { - "name": "condition", - "type": "area", - "label": "Условие", - "placeholder": "Введите условие" - } - ] - }, - { - "name": "else_row", - "type": "row", - "label": "Альтернативный путь", - "link_port": { - "id": "else_output", - "label": "Else" - } - } - ] -} - -# Дескриптор формы для узла Listen -LISTEN_FORM_DESCRIPTOR = { - "elements": [ - { - "name": "event_row", - "type": "row", - "label": "Событие", - "elements": [ - { - "name": "event_name", - "type": "line", - "label": "Событие", - "placeholder": "Идентификатор события" - } - ] - }, - { - "name": "condition_row", - "type": "row", - "label": "Условие", - "elements": [ - { - "name": "condition", - "type": "area", - "label": "Условие", - "placeholder": "Если P([condition(i), [AND, OR]]) == true" - } - ] - }, - { - "name": "then_row", - "type": "row", - "label": "Then", - "link_port": { - "id": "then_output", - "label": "Then" - } - } - ] -} - -# Дескриптор формы для узла Trigger -TRIGGER_FORM_DESCRIPTOR = { - "elements": [ - { - "name": "event_row", - "type": "row", - "label": "Событие", - "elements": [ - { - "name": "event_name", - "type": "line", - "label": "Событие", - "placeholder": "Идентификатор события" - } - ] - }, - { - "name": "context_row", - "type": "row", - "label": "Контекст", - "elements": [ - { - "name": "context", - "type": "area", - "label": "Данные", - "placeholder": "Подготовка указанных переменных окружения в формат запроса JSON" - } - ] - }, - { - "name": "then_row", - "type": "row", - "label": "Then", - "link_port": { - "id": "then_output", - "label": "Then" - } - } - ] -} - -# Дескриптор формы для узла Run -RUN_FORM_DESCRIPTOR = { - "elements": [ - { - "name": "task_row", - "type": "row", - "label": "Задача", - "elements": [ - { - "name": "task", - "type": "select", - "label": "Задача", - "data": ["send_email", "process_data", "generate_report", "validate_input", "transform_data"], - "default": "send_email" - } - ] - }, - { - "name": "context_row", - "type": "row", - "label": "Аргументы", - "elements": [ - { - "name": "context", - "type": "area", - "label": "Аргументы", - "placeholder": "Подготовка указанных переменных окружения в формат запроса JSON" - } - ] - }, - { - "name": "then_row", - "type": "row", - "label": "Then", - "link_port": { - "id": "then_output", - "label": "Then" - } - } - ] -} - -# Дескриптор формы для узла Callback -CALLBACK_FORM_DESCRIPTOR = { - "elements": [ - { - "name": "uri_row", - "type": "row", - "label": "URI", - "elements": [ - { - "name": "uri", - "type": "line", - "label": "Событие", - "placeholder": "URI хука" - } - ] - }, - { - "name": "method_row", - "type": "row", - "label": "Метод", - "elements": [ - { - "name": "method", - "type": "select", - "label": "Метод", - "data": ["POST", "GET", "PUT", "PATCH", "DELETE"], - "default": "POST" - } - ] - }, - { - "name": "headers_row", - "type": "row", - "label": "Заголовки", - "elements": [ - { - "name": "headers", - "type": "area", - "label": "Заголовки", - "placeholder": "Приведение и валидация заголовков" - } - ] - }, - { - "name": "body_row", - "type": "row", - "label": "Данные", - "elements": [ - { - "name": "body", - "type": "area", - "label": "Данные", - "placeholder": "Приведение значений и валидация JSON" - } - ] - }, - { - "name": "sync_row", - "type": "row", - "label": "Ожидать выполнение запроса", - "elements": [ - { - "name": "sync", - "type": "select", - "label": "Ожидать выполнение запроса", - "data": ["Да", "Нет"], - "default": "Да" - } - ] - }, - { - "name": "then_row", - "type": "row", - "label": "Then", - "link_port": { - "id": "then_output", - "label": "Then" - } - } - ] -} - -# Дескриптор формы для узла Switch -SWITCH_FORM_DESCRIPTOR = { - "elements": [ - { - "name": "switch_row", - "type": "row", - "label": "Условие проверки", - "link_port": { - "id": "case_1_output", - "label": "case_1", - "is_addable": True - }, - - "elements": [ - { - "name": "switch_value", - "type": "area", - "label": "Условие проверки", - "placeholder": "Введите условие" - } - ] - }, - { - "name": "default_row", - "type": "row", - "label": "По умолчанию", - "link_port": { - "id": "default_output", - "label": "default" - } - } - ] -} - -# Дескриптор формы для узла Set -SET_FORM_DESCRIPTOR = { - "elements": [ - { - "name": "variable_row", - "type": "row", - "label": "Имя параметра", - "elements": [ - { - "name": "variable", - "type": "line", - "label": "Имя параметра", - "placeholder": "Введите имя параметра" - } - ] - }, - { - "name": "value_row", - "type": "row", - "label": "Параметр", - "elements": [ - { - "name": "value", - "type": "area", - "label": "Параметр", - "placeholder": "Введите значение" - } - ] - }, - { - "name": "link_row", - "type": "row", - "label": "Связь", - "link_port": { - "id": "then_output", - "label": "then" - }, - "elements": [] - } - ] -} - -# Дескриптор формы для узла Wait -WAIT_FORM_DESCRIPTOR = { - "elements": [ - { - "name": "type_row", - "type": "row", - "label": "Параметр", - "elements": [ - { - "name": "type", - "type": "select", - "label": "Параметр", - "data": ["seconds", "datetime"], - "placeholder": "Выбранный вариант" - } - ] - }, - { - "name": "wait_for_row", - "type": "row", - "label": "Время", - "elements": [ - { - "name": "wait_for", - "type": "number", - "label": "Время", - "placeholder": "Вычислить значение ожидания в секундах" - } - ] - }, - { - "name": "wait_datetime_row", - "type": "row", - "label": "Подождать", - "elements": [ - { - "name": "wait_datetime", - "type": "date", - "label": "Подождать", - "placeholder": "Вычислить значение до определённого времени" - } - ] - }, - { - "name": "then_row", - "type": "row", - "label": "Переход", - "link_port": { - "id": "then_output", - "label": "then" - } - } - ] -} - -# Дескриптор формы для узла While -WHILE_FORM_DESCRIPTOR = { - "elements": [ - { - "name": "condition_row", - "type": "row", - "label": "Параметр", - "link_port": { - "id": "then_output", - "label": "Then" - }, - "elements": [ - { - "name": "condition", - "type": "area", - "label": "Параметр", - "placeholder": "P(condition) == true" - } - ] - }, - { - "name": "else_row", - "type": "row", - "label": "Альтернативный путь", - "link_port": { - "id": "else_output", - "label": "Else" - } - } - ] -} - -# Дескриптор формы для узла Each -EACH_FORM_DESCRIPTOR = { - "elements": [ - { - "name": "list_row", - "type": "row", - "label": "Список", - "link_port": { - "id": "then_output", - "label": "Then" - }, - "elements": [ - { - "name": "list", - "type": "line", - "label": "Список", - "placeholder": "Валидация списка и получение очередного value из списка" - } - ] - }, - { - "name": "else_row", - "type": "row", - "label": "Альтернативный путь", - "link_port": { - "id": "else_output", - "label": "Else" - } - } - ] -} - -# Маппинг типов узлов на дескрипторы форм -FORM_DESCRIPTORS = { - "IF": IF_FORM_DESCRIPTOR, - "LISTEN": LISTEN_FORM_DESCRIPTOR, - "TRIGGER": TRIGGER_FORM_DESCRIPTOR, - "RUN": RUN_FORM_DESCRIPTOR, - "CALLBACK": CALLBACK_FORM_DESCRIPTOR, - "SWITCH": SWITCH_FORM_DESCRIPTOR, - "SET": SET_FORM_DESCRIPTOR, - "WAIT": WAIT_FORM_DESCRIPTOR, - "WHILE": WHILE_FORM_DESCRIPTOR, - "EACH": EACH_FORM_DESCRIPTOR, -} - -def get_form_descriptor(node_type: str) -> Dict[str, Any]: - """ - Получить дескриптор формы для указанного типа узла - - Args: - node_type: Тип узла (например, "node_if") - - Returns: - Dict с дескриптором формы или пустой dict если тип не найден - """ - return FORM_DESCRIPTORS.get(node_type, {}) diff --git a/core/vork_node_start.py b/core/vork_node_start.py deleted file mode 100644 index 970ba22..0000000 --- a/core/vork_node_start.py +++ /dev/null @@ -1,63 +0,0 @@ -from typing import Dict, Any -from .vork_node import VorkNode -from model_nodes.node_start_models import ( - StartNodeData, - StartNodeCoreSchema, - StartNodeCoreSchemaData -) - - -class VorkNodeStart(VorkNode): - - def __init__(self, data: Dict[str, Any], links: Dict[str, Any] = None): - """ - Инициализация стартового узла - """ - super().__init__(data, links or {}) - - @property - def id(self) -> str: - return "START" - - @classmethod - def form(cls) -> StartNodeCoreSchema: - """ - Возвращает схему узла start для UI - """ - return StartNodeCoreSchema() - - def validate(self) -> StartNodeCoreSchema: - """ - Валидирует данные узла start и возвращает схему - """ - try: - # Валидируем данные узла - validated_data = self.validate_data() - - node_data = StartNodeCoreSchemaData( - node_port_number=0, - ) - - # Создаем схему с валидированными данными - return StartNodeCoreSchema( - ps_id=validated_data.ps_id, - node_type=validated_data.node_type, - data=node_data - ) - except Exception as e: - print(f"Start node validation error: {e}") - raise - - def validate_data(self) -> StartNodeData: - """ - Валидирует данные узла start - """ - return StartNodeData(**self.data) - - def process(self, context): - """ - Обрабатывает узел start - точка входа в процесс - """ - # Start узел просто передает управление дальше - # Здесь может быть логика инициализации процесса - pass diff --git a/core/vork_node_test.py b/core/vork_node_test.py new file mode 100644 index 0000000..febbb37 --- /dev/null +++ b/core/vork_node_test.py @@ -0,0 +1,49 @@ +from typing import Dict, Any +from .vork_node import VorkNode +from model_nodes.node_test_models import ( + TestNodeData, + TestNodeCoreSchema, + TestNodeCoreSchemaData +) + + +class VorkNodeTest(VorkNode): + + def __init__(self, data: Dict[str, Any], links: Dict[str, Any] = None): + """ + Инициализация узла test + """ + super().__init__(data, links or {}) + + @property + def id(self) -> str: + return "TEST" + + @classmethod + def form(cls) -> TestNodeCoreSchema: + """ + Возвращает схему узла test для UI + """ + return TestNodeCoreSchema() + + def validate(self) -> TestNodeCoreSchema: + """ + Валидирует данные узла test и возвращает схему + """ + try: + validated_data = self.validate_data() + node_data = TestNodeCoreSchemaData(node_port_number=0) + return TestNodeCoreSchema( + ps_id=validated_data.ps_id, + node_type=validated_data.node_type, + data=node_data + ) + except Exception as e: + print(f"Test node validation error: {e}") + raise + + def validate_data(self) -> TestNodeData: + return TestNodeData(**self.data) + + def process(self, context): + pass diff --git a/model_nodes/__init__.py b/model_nodes/__init__.py index fce364a..fb99513 100644 --- a/model_nodes/__init__.py +++ b/model_nodes/__init__.py @@ -38,12 +38,12 @@ from .node_if_models import ( IfNodeCoreSchemaData ) -# Экспорты для моделей узла start -from .node_start_models import ( - StartNodeData, - StartNodeLinks, - StartNodeCoreSchema, - StartNodeCoreSchemaData +# Экспорты для моделей узла test (ранее start) +from .node_test_models import ( + TestNodeData, + TestNodeLinks, + TestNodeCoreSchema, + TestNodeCoreSchemaData ) # Экспорты для моделей узла switch @@ -123,11 +123,11 @@ __all__ = [ "IfNodeCoreSchema", "IfNodeCoreSchemaData", - # Start node models - "StartNodeData", - "StartNodeLinks", - "StartNodeCoreSchema", - "StartNodeCoreSchemaData", + # Test node models + "TestNodeData", + "TestNodeLinks", + "TestNodeCoreSchema", + "TestNodeCoreSchemaData", # Switch node models "SwitchNodeData", diff --git a/model_nodes/form_base_descriptor_models.py b/model_nodes/form_base_descriptor_models.py new file mode 100644 index 0000000..70277df --- /dev/null +++ b/model_nodes/form_base_descriptor_models.py @@ -0,0 +1,75 @@ +from __future__ import annotations +from typing import Optional, Annotated, Literal, List +from pydantic import BaseModel, Field + + +class LinkPort(BaseModel): + id: str + label: str + is_addable: Optional[bool] = None + + +class LineElement(BaseModel): + type: Literal['line'] + name: str + label: str + placeholder: Optional[str] = None + + +class AreaElement(BaseModel): + type: Literal['area'] + name: str + label: str + placeholder: Optional[str] = None + + +class SelectElement(BaseModel): + type: Literal['select'] + name: str + label: str + data: List[str] + default: Optional[str] = None + placeholder: Optional[str] = None + + +class NumberElement(BaseModel): + type: Literal['number'] + name: str + label: str + placeholder: Optional[str] = None + + +class DateElement(BaseModel): + type: Literal['date'] + name: str + label: str + placeholder: Optional[str] = None + + +FieldElement = Annotated[ + LineElement | AreaElement | SelectElement | NumberElement | DateElement, + Field(discriminator='type'), +] + + +class RowElement(BaseModel): + type: Literal['row'] + name: str + label: str + link_port: Optional[LinkPort] = None + elements: Optional[List[FieldElement]] = None + + +class FormDescriptor(BaseModel): + elements: List[RowElement] + + +# Descriptor-suffixed aliases for clarity (backward compatible) +LinkPortDescriptor = LinkPort +LineElementDescriptor = LineElement +AreaElementDescriptor = AreaElement +SelectElementDescriptor = SelectElement +NumberElementDescriptor = NumberElement +DateElementDescriptor = DateElement +RowDescriptor = RowElement +FormDescriptorModel = FormDescriptor diff --git a/model_nodes/node_callback_models.py b/model_nodes/node_callback_models.py index b31b630..a0f17c6 100644 --- a/model_nodes/node_callback_models.py +++ b/model_nodes/node_callback_models.py @@ -1,5 +1,6 @@ from typing import Optional from pydantic import BaseModel, Field +from .form_base_descriptor_models import FormDescriptor, RowElement, LineElement, AreaElement, SelectElement, LinkPort class CallbackNodeData(BaseModel): @@ -34,3 +35,83 @@ class CallbackNodeCoreSchema(BaseModel): parent_id: Optional[int] = Field(default=None, description="ID родительского узла") parent_port_number: Optional[int] = Field(default=None, description="Номер порта родительского узла") data: Optional[CallbackNodeCoreSchemaData] = Field(default=None, description="Данные узла") + + +# Дескриптор формы узла CALLBACK +CALLBACK_FORM_DESCRIPTOR = FormDescriptor( + elements=[ + RowElement( + name="uri_row", + type="row", + label="URI", + elements=[ + LineElement( + name="uri", + type="line", + label="URI", + placeholder="Webhook URL", + ) + ], + ), + RowElement( + name="method_row", + type="row", + label="Method", + elements=[ + SelectElement( + name="method", + type="select", + label="Method", + data=["POST", "GET", "PUT", "PATCH", "DELETE"], + default="POST", + ) + ], + ), + RowElement( + name="headers_row", + type="row", + label="Headers", + elements=[ + AreaElement( + name="headers", + type="area", + label="Headers", + placeholder="Normalize and validate headers", + ) + ], + ), + RowElement( + name="body_row", + type="row", + label="Body", + elements=[ + AreaElement( + name="body", + type="area", + label="Data", + placeholder="Normalize values and validate JSON", + ) + ], + ), + RowElement( + name="sync_row", + type="row", + label="Wait for request completion", + elements=[ + SelectElement( + name="sync", + type="select", + label="Wait for request completion", + data=["Yes", "No"], + default="Yes", + ) + ], + ), + RowElement( + name="then_row", + type="row", + label="Then", + link_port=LinkPort(id="then_output", label="Then"), + ), + ] +) diff --git a/model_nodes/node_each_models.py b/model_nodes/node_each_models.py index 54ec70a..76cf954 100644 --- a/model_nodes/node_each_models.py +++ b/model_nodes/node_each_models.py @@ -1,5 +1,6 @@ from typing import Optional from pydantic import BaseModel, Field +from .form_base_descriptor_models import FormDescriptor, RowElement, LineElement, LinkPort class EachNodeData(BaseModel): @@ -35,3 +36,30 @@ class EachNodeCoreSchema(BaseModel): parent_id: Optional[int] = Field(default=None, description="ID родительского узла") parent_port_number: Optional[int] = Field(default=None, description="Номер порта родительского узла") data: Optional[EachNodeCoreSchemaData] = Field(default=None, description="Данные узла") + + +# Дескриптор формы узла EACH +EACH_FORM_DESCRIPTOR = FormDescriptor( + elements=[ + RowElement( + name="list_row", + type="row", + label="List", + link_port=LinkPort(id="then_output", label="Then"), + elements=[ + LineElement( + name="list", + type="line", + label="List", + placeholder="Validate list and extract next value from list", + ) + ], + ), + RowElement( + name="else_row", + type="row", + label="Alternative path", + link_port=LinkPort(id="else_output", label="Else"), + ), + ] +) diff --git a/model_nodes/node_if_models.py b/model_nodes/node_if_models.py index 25c861c..c8bd360 100644 --- a/model_nodes/node_if_models.py +++ b/model_nodes/node_if_models.py @@ -1,5 +1,6 @@ from typing import Optional from pydantic import BaseModel, Field +from .form_base_descriptor_models import FormDescriptor, RowElement, AreaElement, LinkPort class IfNodeData(BaseModel): @@ -35,3 +36,30 @@ class IfNodeCoreSchema(BaseModel): parent_id: Optional[int] = Field(default=None, description="ID родительского узла") parent_port_number: Optional[int] = Field(default=None, description="Номер порта родительского узла") data: Optional[IfNodeCoreSchemaData] = Field(default=None, description="Данные узла") + + +# Дескриптор формы узла IF +IF_FORM_DESCRIPTOR = FormDescriptor( + elements=[ + RowElement( + name="condition_row", + type="row", + label="Condition", + link_port=LinkPort(id="then_output", label="Then"), + elements=[ + AreaElement( + name="condition", + type="area", + label="Condition", + placeholder="Enter condition", + ) + ], + ), + RowElement( + name="else_row", + type="row", + label="Alternative path", + link_port=LinkPort(id="else_output", label="Else"), + ), + ] +) diff --git a/model_nodes/node_listen_models.py b/model_nodes/node_listen_models.py index 8b46d59..8eb3ae6 100644 --- a/model_nodes/node_listen_models.py +++ b/model_nodes/node_listen_models.py @@ -1,5 +1,6 @@ from typing import Optional from pydantic import BaseModel, Field +from .form_base_descriptor_models import FormDescriptor, RowElement, LineElement, AreaElement, LinkPort class ListenNodeData(BaseModel): @@ -36,3 +37,42 @@ class ListenNodeCoreSchema(BaseModel): parent_id: Optional[int] = Field(default=None, description="ID родительского узла") parent_port_number: Optional[int] = Field(default=None, description="Номер порта родительского узла") data: Optional[ListenNodeCoreSchemaData] = Field(default=None, description="Данные узла") + + +# Дескриптор формы узла LISTEN +LISTEN_FORM_DESCRIPTOR = FormDescriptor( + elements=[ + RowElement( + name="event_row", + type="row", + label="Event", + elements=[ + LineElement( + name="event_name", + type="line", + label="Event", + placeholder="Event identifier", + ) + ], + ), + RowElement( + name="condition_row", + type="row", + label="Condition", + elements=[ + AreaElement( + name="condition", + type="area", + label="Condition", + placeholder="If P([condition(i), [AND, OR]]) == true", + ) + ], + ), + RowElement( + name="then_row", + type="row", + label="Then", + link_port=LinkPort(id="then_output", label="Then"), + ), + ] +) diff --git a/model_nodes/node_run_models.py b/model_nodes/node_run_models.py index 63eaf3f..0738fe7 100644 --- a/model_nodes/node_run_models.py +++ b/model_nodes/node_run_models.py @@ -1,5 +1,6 @@ from typing import Optional from pydantic import BaseModel, Field +from .form_base_descriptor_models import FormDescriptor, RowElement, AreaElement, SelectElement, LinkPort class RunNodeData(BaseModel): @@ -34,3 +35,43 @@ class RunNodeCoreSchema(BaseModel): parent_id: Optional[int] = Field(default=None, description="ID родительского узла") parent_port_number: Optional[int] = Field(default=None, description="Номер порта родительского узла") data: Optional[RunNodeCoreSchemaData] = Field(default=None, description="Данные узла") + + +# Дескриптор формы для узла Run +RUN_FORM_DESCRIPTOR = FormDescriptor( + elements=[ + RowElement( + name="task_row", + type="row", + label="Task", + elements=[ + SelectElement( + name="task", + type="select", + label="Task", + data=["send_email", "process_data", "generate_report", "validate_input", "transform_data"], + default="send_email", + ) + ], + ), + RowElement( + name="context_row", + type="row", + label="Arguments", + elements=[ + AreaElement( + name="context", + type="area", + label="Arguments", + placeholder="Build request JSON from provided environment variables", + ) + ], + ), + RowElement( + name="then_row", + type="row", + label="Then", + link_port=LinkPort(id="then_output", label="Then"), + ), + ] +) diff --git a/model_nodes/node_set_models.py b/model_nodes/node_set_models.py index 61fc015..7bd1473 100644 --- a/model_nodes/node_set_models.py +++ b/model_nodes/node_set_models.py @@ -1,5 +1,6 @@ from typing import Optional from pydantic import BaseModel, Field +from .form_base_descriptor_models import FormDescriptor, RowElement, LineElement, AreaElement, LinkPort class SetNodeData(BaseModel): @@ -34,3 +35,43 @@ class SetNodeCoreSchema(BaseModel): parent_id: Optional[int] = Field(default=None, description="ID родительского узла") parent_port_number: Optional[int] = Field(default=None, description="Номер порта родительского узла") data: Optional[SetNodeCoreSchemaData] = Field(default=None, description="Данные узла") + + +# Дескриптор формы узла SET +SET_FORM_DESCRIPTOR = FormDescriptor( + elements=[ + RowElement( + name="variable_row", + type="row", + label="Parameter name", + elements=[ + LineElement( + name="variable", + type="line", + label="Parameter name", + placeholder="Enter parameter name", + ) + ], + ), + RowElement( + name="value_row", + type="row", + label="Value", + elements=[ + AreaElement( + name="value", + type="area", + label="Value", + placeholder="Enter value", + ) + ], + ), + RowElement( + name="link_row", + type="row", + label="Link", + link_port=LinkPort(id="then_output", label="then"), + elements=[], + ), + ] +) diff --git a/model_nodes/node_switch_models.py b/model_nodes/node_switch_models.py index 7c4cd2b..7d4e8c2 100644 --- a/model_nodes/node_switch_models.py +++ b/model_nodes/node_switch_models.py @@ -1,5 +1,6 @@ from typing import Optional from pydantic import BaseModel, Field +from .form_base_descriptor_models import FormDescriptor, RowElement, AreaElement, LinkPort class SwitchNodeData(BaseModel): @@ -35,3 +36,30 @@ class SwitchNodeCoreSchema(BaseModel): parent_id: Optional[int] = Field(default=None, description="ID родительского узла") parent_port_number: Optional[int] = Field(default=None, description="Номер порта родительского узла") data: Optional[SwitchNodeCoreSchemaData] = Field(default=None, description="Данные узла") + + +# Дескриптор формы узла SWITCH +SWITCH_FORM_DESCRIPTOR = FormDescriptor( + elements=[ + RowElement( + name="switch_row", + type="row", + label="Switch condition", + link_port=LinkPort(id="case_1_output", label="case_1", is_addable=True), + elements=[ + AreaElement( + name="switch_value", + type="area", + label="Switch condition", + placeholder="Enter condition", + ) + ], + ), + RowElement( + name="default_row", + type="row", + label="Default", + link_port=LinkPort(id="default_output", label="default"), + ), + ] +) diff --git a/model_nodes/node_start_models.py b/model_nodes/node_test_models.py similarity index 60% rename from model_nodes/node_start_models.py rename to model_nodes/node_test_models.py index 4a3d4b8..f50b87e 100644 --- a/model_nodes/node_start_models.py +++ b/model_nodes/node_test_models.py @@ -1,33 +1,33 @@ -from typing import Optional, Dict, Any +from typing import Optional from pydantic import BaseModel, Field -class StartNodeData(BaseModel): +class TestNodeData(BaseModel): """ - Pydantic модель для валидации данных узла start + Pydantic модель для валидации данных узла test """ ps_id: Optional[int] = Field(default=None, description="ID процесса") node_type: Optional[str] = Field(default=None, description="Тип узла") -class StartNodeLinks(BaseModel): +class TestNodeLinks(BaseModel): """ - Pydantic модель для валидации связей узла start + Pydantic модель для валидации связей узла test """ - # Start узел не имеет родительских связей, только исходящие + # Test узел не имеет родительских связей, только исходящие -class StartNodeCoreSchemaData(BaseModel): +class TestNodeCoreSchemaData(BaseModel): """ - Pydantic модель для данных портов узла start + Pydantic модель для данных портов узла test """ node_port_number: Optional[int] = Field(default=0, description="Номер порта для перехода по Связи Then (LINK)") -class StartNodeCoreSchema(BaseModel): +class TestNodeCoreSchema(BaseModel): """ - Pydantic модель для схемы узла start + Pydantic модель для схемы узла test """ ps_id: Optional[int] = Field(default=None, description="ID процесса") node_type: Optional[str] = Field(default=None, description="Тип узла") - data: Optional[StartNodeCoreSchemaData] = Field(default=None, description="Данные узла") + data: Optional[TestNodeCoreSchemaData] = Field(default=None, description="Данные узла") diff --git a/model_nodes/node_trigger_models.py b/model_nodes/node_trigger_models.py index f0774e2..7814e1b 100644 --- a/model_nodes/node_trigger_models.py +++ b/model_nodes/node_trigger_models.py @@ -1,5 +1,6 @@ from typing import Optional from pydantic import BaseModel, Field +from .form_base_descriptor_models import FormDescriptor, RowElement, LineElement, AreaElement, LinkPort class TriggerNodeData(BaseModel): @@ -34,3 +35,42 @@ class TriggerNodeCoreSchema(BaseModel): parent_id: Optional[int] = Field(default=None, description="ID родительского узла") parent_port_number: Optional[int] = Field(default=None, description="Номер порта родительского узла") data: Optional[TriggerNodeCoreSchemaData] = Field(default=None, description="Данные узла") + + +# Дескриптор формы узла TRIGGER +TRIGGER_FORM_DESCRIPTOR = FormDescriptor( + elements=[ + RowElement( + name="event_row", + type="row", + label="Event", + elements=[ + LineElement( + name="event_name", + type="line", + label="Event", + placeholder="Event identifier", + ) + ], + ), + RowElement( + name="context_row", + type="row", + label="Context", + elements=[ + AreaElement( + name="context", + type="area", + label="Payload", + placeholder="Build request JSON from provided environment variables", + ) + ], + ), + RowElement( + name="then_row", + type="row", + label="Then", + link_port=LinkPort(id="then_output", label="Then"), + ), + ] +) diff --git a/model_nodes/node_wait_models.py b/model_nodes/node_wait_models.py index af9278d..352f5c7 100644 --- a/model_nodes/node_wait_models.py +++ b/model_nodes/node_wait_models.py @@ -1,5 +1,6 @@ from typing import Optional from pydantic import BaseModel, Field +from .form_base_descriptor_models import FormDescriptor, RowElement, SelectElement, NumberElement, DateElement, LinkPort class WaitNodeData(BaseModel): @@ -34,3 +35,56 @@ class WaitNodeCoreSchema(BaseModel): parent_id: Optional[int] = Field(default=None, description="ID родительского узла") parent_port_number: Optional[int] = Field(default=None, description="Номер порта родительского узла") data: Optional[WaitNodeCoreSchemaData] = Field(default=None, description="Данные узла") + + +# Дескриптор формы узла WAIT +WAIT_FORM_DESCRIPTOR = FormDescriptor( + elements=[ + RowElement( + name="type_row", + type="row", + label="Parameter", + elements=[ + SelectElement( + name="type", + type="select", + label="Parameter", + data=["seconds", "datetime"], + placeholder="Selected option", + ) + ], + ), + RowElement( + name="wait_for_row", + type="row", + label="Time", + elements=[ + NumberElement( + name="wait_for", + type="number", + label="Time", + placeholder="Compute wait time in seconds", + ) + ], + ), + RowElement( + name="wait_datetime_row", + type="row", + label="Wait until", + elements=[ + DateElement( + name="wait_datetime", + type="date", + label="Wait until", + placeholder="Compute value until specific datetime", + ) + ], + ), + RowElement( + name="then_row", + type="row", + label="Transition", + link_port=LinkPort(id="then_output", label="then"), + ), + ] +) diff --git a/model_nodes/node_while_models.py b/model_nodes/node_while_models.py index 96354a2..b4bcd6c 100644 --- a/model_nodes/node_while_models.py +++ b/model_nodes/node_while_models.py @@ -1,5 +1,6 @@ from typing import Optional from pydantic import BaseModel, Field +from .form_base_descriptor_models import FormDescriptor, RowElement, AreaElement, LinkPort class WhileNodeData(BaseModel): @@ -35,3 +36,30 @@ class WhileNodeCoreSchema(BaseModel): parent_id: Optional[int] = Field(default=None, description="ID родительского узла") parent_port_number: Optional[int] = Field(default=None, description="Номер порта родительского узла") data: Optional[WhileNodeCoreSchemaData] = Field(default=None, description="Данные узла") + + +# Дескриптор формы узла WHILE +WHILE_FORM_DESCRIPTOR = FormDescriptor( + elements=[ + RowElement( + name="condition_row", + type="row", + label="Parameter", + link_port=LinkPort(id="then_output", label="Then"), + elements=[ + AreaElement( + name="condition", + type="area", + label="Parameter", + placeholder="P(condition) == true", + ) + ], + ), + RowElement( + name="else_row", + type="row", + label="Alternative path", + link_port=LinkPort(id="else_output", label="Else"), + ), + ] +) diff --git a/nodes/vork_node_callback.py b/nodes/vork_node_callback.py index 8aa569f..a1f12bd 100644 --- a/nodes/vork_node_callback.py +++ b/nodes/vork_node_callback.py @@ -1,13 +1,11 @@ from typing import Dict, Any -import requests -import json from core import VorkNode -from core.form_descriptors import get_form_descriptor from model_nodes.node_callback_models import ( CallbackNodeData, CallbackNodeLinks, CallbackNodeCoreSchema, - CallbackNodeCoreSchemaData + CallbackNodeCoreSchemaData, + CALLBACK_FORM_DESCRIPTOR, ) @@ -28,7 +26,7 @@ class VorkNodeCallback(VorkNode): """ Возвращает статический дескриптор формы для узла Callback """ - return get_form_descriptor("CALLBACK") + return CALLBACK_FORM_DESCRIPTOR def validate(self) -> CallbackNodeCoreSchema: """ diff --git a/nodes/vork_node_each.py b/nodes/vork_node_each.py index fccc33d..283dd30 100644 --- a/nodes/vork_node_each.py +++ b/nodes/vork_node_each.py @@ -1,11 +1,11 @@ from typing import Dict, Any from core import VorkNode -from core.form_descriptors import get_form_descriptor from model_nodes.node_each_models import ( EachNodeData, EachNodeLinks, EachNodeCoreSchema, - EachNodeCoreSchemaData + EachNodeCoreSchemaData, + EACH_FORM_DESCRIPTOR, ) @@ -26,7 +26,7 @@ class VorkNodeEach(VorkNode): """ Возвращает статический дескриптор формы для узла Each """ - return get_form_descriptor("EACH") + return EACH_FORM_DESCRIPTOR def validate(self) -> EachNodeCoreSchema: """ diff --git a/nodes/vork_node_if.py b/nodes/vork_node_if.py index 673e511..a0fef48 100644 --- a/nodes/vork_node_if.py +++ b/nodes/vork_node_if.py @@ -1,11 +1,11 @@ from typing import Any, Dict from core import VorkNode -from core.form_descriptors import get_form_descriptor from model_nodes.node_if_models import ( IfNodeData, IfNodeLinks, IfNodeCoreSchema, - IfNodeCoreSchemaData + IfNodeCoreSchemaData, + IF_FORM_DESCRIPTOR, ) @@ -20,7 +20,7 @@ class VorkNodeIf(VorkNode): """ Возвращает статический дескриптор формы для узла IF """ - return get_form_descriptor("IF") + return IF_FORM_DESCRIPTOR def validate(self) -> IfNodeCoreSchema: """ diff --git a/nodes/vork_node_listen.py b/nodes/vork_node_listen.py index 277bd94..9dad076 100644 --- a/nodes/vork_node_listen.py +++ b/nodes/vork_node_listen.py @@ -1,11 +1,11 @@ from typing import Dict, Any from core import VorkNode -from core.form_descriptors import get_form_descriptor from model_nodes.node_listen_models import ( ListenNodeData, ListenNodeLinks, ListenNodeCoreSchema, - ListenNodeCoreSchemaData + ListenNodeCoreSchemaData, + LISTEN_FORM_DESCRIPTOR, ) @@ -26,7 +26,7 @@ class VorkNodeListen(VorkNode): """ Возвращает статический дескриптор формы для узла Listen """ - return get_form_descriptor("LISTEN") + return LISTEN_FORM_DESCRIPTOR def validate(self) -> ListenNodeCoreSchema: """ diff --git a/nodes/vork_node_run.py b/nodes/vork_node_run.py index ab96b95..ba5b056 100644 --- a/nodes/vork_node_run.py +++ b/nodes/vork_node_run.py @@ -1,12 +1,11 @@ from typing import Dict, Any -import json from core import VorkNode -from core.form_descriptors import get_form_descriptor from model_nodes.node_run_models import ( RunNodeData, RunNodeLinks, RunNodeCoreSchema, - RunNodeCoreSchemaData + RunNodeCoreSchemaData, + RUN_FORM_DESCRIPTOR, ) @@ -27,7 +26,7 @@ class VorkNodeRun(VorkNode): """ Возвращает статический дескриптор формы для узла Run """ - return get_form_descriptor("RUN") + return RUN_FORM_DESCRIPTOR def validate(self) -> RunNodeCoreSchema: """ diff --git a/nodes/vork_node_set.py b/nodes/vork_node_set.py index dbebd58..2ab7530 100644 --- a/nodes/vork_node_set.py +++ b/nodes/vork_node_set.py @@ -1,11 +1,11 @@ from typing import Dict, Any from core import VorkNode -from core.form_descriptors import get_form_descriptor from model_nodes.node_set_models import ( SetNodeData, SetNodeLinks, SetNodeCoreSchema, - SetNodeCoreSchemaData + SetNodeCoreSchemaData, + SET_FORM_DESCRIPTOR, ) @@ -26,7 +26,7 @@ class VorkNodeSet(VorkNode): """ Возвращает статический дескриптор формы для узла Set """ - return get_form_descriptor("SET") + return SET_FORM_DESCRIPTOR def validate(self) -> SetNodeCoreSchema: """ diff --git a/nodes/vork_node_switch.py b/nodes/vork_node_switch.py index 601d483..0aa8e66 100644 --- a/nodes/vork_node_switch.py +++ b/nodes/vork_node_switch.py @@ -1,11 +1,11 @@ from typing import Dict, Any from core import VorkNode -from core.form_descriptors import get_form_descriptor from model_nodes.node_switch_models import ( SwitchNodeData, SwitchNodeLinks, SwitchNodeCoreSchema, - SwitchNodeCoreSchemaData + SwitchNodeCoreSchemaData, + SWITCH_FORM_DESCRIPTOR, ) @@ -26,7 +26,7 @@ class VorkNodeSwitch(VorkNode): """ Возвращает статический дескриптор формы для узла Switch """ - return get_form_descriptor("SWITCH") + return SWITCH_FORM_DESCRIPTOR def validate(self) -> SwitchNodeCoreSchema: """ diff --git a/nodes/vork_node_trigger.py b/nodes/vork_node_trigger.py index c94debf..2f8504d 100644 --- a/nodes/vork_node_trigger.py +++ b/nodes/vork_node_trigger.py @@ -1,11 +1,11 @@ from typing import Dict, Any from core import VorkNode -from core.form_descriptors import get_form_descriptor from model_nodes.node_trigger_models import ( TriggerNodeData, TriggerNodeLinks, TriggerNodeCoreSchema, - TriggerNodeCoreSchemaData + TriggerNodeCoreSchemaData, + TRIGGER_FORM_DESCRIPTOR, ) @@ -26,7 +26,7 @@ class VorkNodeTrigger(VorkNode): """ Возвращает статический дескриптор формы для узла Trigger """ - return get_form_descriptor("TRIGGER") + return TRIGGER_FORM_DESCRIPTOR def validate(self) -> TriggerNodeCoreSchema: """ diff --git a/nodes/vork_node_wait.py b/nodes/vork_node_wait.py index e533947..20fab2c 100644 --- a/nodes/vork_node_wait.py +++ b/nodes/vork_node_wait.py @@ -1,11 +1,11 @@ from typing import Dict, Any from core import VorkNode -from core.form_descriptors import get_form_descriptor from model_nodes.node_wait_models import ( WaitNodeData, WaitNodeLinks, WaitNodeCoreSchema, - WaitNodeCoreSchemaData + WaitNodeCoreSchemaData, + WAIT_FORM_DESCRIPTOR, ) @@ -26,7 +26,7 @@ class VorkNodeWait(VorkNode): """ Возвращает статический дескриптор формы для узла Wait """ - return get_form_descriptor("WAIT") + return WAIT_FORM_DESCRIPTOR def validate(self) -> WaitNodeCoreSchema: """ diff --git a/nodes/vork_node_while.py b/nodes/vork_node_while.py index cecf6c6..a327d97 100644 --- a/nodes/vork_node_while.py +++ b/nodes/vork_node_while.py @@ -1,11 +1,11 @@ from typing import Dict, Any from core import VorkNode -from core.form_descriptors import get_form_descriptor from model_nodes.node_while_models import ( WhileNodeData, WhileNodeLinks, WhileNodeCoreSchema, - WhileNodeCoreSchemaData + WhileNodeCoreSchemaData, + WHILE_FORM_DESCRIPTOR, ) @@ -26,7 +26,7 @@ class VorkNodeWhile(VorkNode): """ Возвращает статический дескриптор формы для узла While """ - return get_form_descriptor("WHILE") + return WHILE_FORM_DESCRIPTOR def validate(self) -> WhileNodeCoreSchema: """ diff --git a/poetry.lock b/poetry.lock index 13c09aa..9a29d49 100644 --- a/poetry.lock +++ b/poetry.lock @@ -340,5 +340,5 @@ typing-extensions = ">=4.12.0" [metadata] lock-version = "2.1" -python-versions = ">=3.9" -content-hash = "903e152c7357bab4a5e2958b70731a876ff1280002b940bbf5d3d859ffa0d379" +python-versions = "^3.9" +content-hash = "01d51b88c538d68359b01cf3a28e98633fafdf244e53550b790cb4ddd44eecac"