feat: pydantic descriptors
This commit is contained in:
@@ -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",
|
||||
|
75
model_nodes/form_base_descriptor_models.py
Normal file
75
model_nodes/form_base_descriptor_models.py
Normal file
@@ -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
|
@@ -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"),
|
||||
),
|
||||
]
|
||||
)
|
||||
|
@@ -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"),
|
||||
),
|
||||
]
|
||||
)
|
||||
|
@@ -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"),
|
||||
),
|
||||
]
|
||||
)
|
||||
|
@@ -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"),
|
||||
),
|
||||
]
|
||||
)
|
||||
|
@@ -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"),
|
||||
),
|
||||
]
|
||||
)
|
||||
|
@@ -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=[],
|
||||
),
|
||||
]
|
||||
)
|
||||
|
@@ -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"),
|
||||
),
|
||||
]
|
||||
)
|
||||
|
@@ -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="Данные узла")
|
@@ -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"),
|
||||
),
|
||||
]
|
||||
)
|
||||
|
@@ -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"),
|
||||
),
|
||||
]
|
||||
)
|
||||
|
@@ -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"),
|
||||
),
|
||||
]
|
||||
)
|
||||
|
Reference in New Issue
Block a user