1+ /**
2+ * Базовый класс для определения ноды в визуальном редакторе.
3+ * Используется как единый формат для всех нод - и backend и frontend.
4+ */
5+ class NodeDefinition {
6+ constructor ( config ) {
7+ this . type = config . type ;
8+ this . category = config . category || 'Other' ;
9+ this . label = config . label || config . type ;
10+ this . description = config . description || '' ;
11+
12+ // Функции для вычисления пинов динамически (поддержка conditional pins)
13+ this . computeInputs = config . computeInputs || ( ( ) => [ ] ) ;
14+ this . computeOutputs = config . computeOutputs || ( ( ) => [ ] ) ;
15+
16+ // Статичные пиньи (fallback для обратной совместимости)
17+ this . pins = config . pins || { inputs : [ ] , outputs : [ ] } ;
18+
19+ // Исполнители ноды
20+ // executor - для action нод с exec пинами (асинхронный)
21+ // evaluator - для data пинов (вычисление значений)
22+ this . executor = config . executor || null ;
23+ this . evaluator = config . evaluator || null ;
24+
25+ // Метаданные ноды
26+ this . defaultData = config . defaultData || { } ;
27+ this . theme = config . theme || { } ;
28+ this . icon = config . icon || null ;
29+ this . graphType = config . graphType || 'ALL' ; // 'COMMAND', 'EVENT', 'ALL'
30+
31+ // Валидация
32+ if ( ! this . type ) {
33+ throw new Error ( 'NodeDefinition: type is required' ) ;
34+ }
35+ }
36+
37+ /**
38+ * Получить входные пиньи для данного состояния ноды
39+ * @param {object } data - данные ноды (для условных пиннов)
40+ * @returns {Array } массив описаний входных пиннов
41+ */
42+ getInputs ( data = { } ) {
43+ if ( typeof this . computeInputs === 'function' ) {
44+ return this . computeInputs ( data ) ;
45+ }
46+ return this . pins . inputs || [ ] ;
47+ }
48+
49+ /**
50+ * Получить выходные пиньи для данного состояния ноды
51+ * @param {object } data - данные ноды (для условных пиннов)
52+ * @returns {Array } массив описаний выходных пиннов
53+ */
54+ getOutputs ( data = { } ) {
55+ if ( typeof this . computeOutputs === 'function' ) {
56+ return this . computeOutputs ( data ) ;
57+ }
58+ return this . pins . outputs || [ ] ;
59+ }
60+
61+ /**
62+ * Проверить, является ли нода action-нодой (с exec пинами)
63+ */
64+ isActionNode ( ) {
65+ const inputs = this . getInputs ( ) ;
66+ return inputs . some ( pin => pin . type === 'Exec' ) ;
67+ }
68+
69+ /**
70+ * Проверить, является ли нода data-нодой (только вычисляемые значения)
71+ */
72+ isDataNode ( ) {
73+ return ! this . isActionNode ( ) ;
74+ }
75+
76+ /**
77+ * Проверить, есть ли у ноды executor
78+ */
79+ hasExecutor ( ) {
80+ return typeof this . executor === 'function' ;
81+ }
82+
83+ /**
84+ * Проверить, есть ли у ноды evaluator
85+ */
86+ hasEvaluator ( ) {
87+ return typeof this . evaluator === 'function' ;
88+ }
89+
90+ /**
91+ * Конвертировать в JSON-сериализуемый формат
92+ * Используется для отправки в frontend
93+ */
94+ toJSON ( ) {
95+ return {
96+ type : this . type ,
97+ category : this . category ,
98+ label : this . label ,
99+ description : this . description ,
100+ pins : {
101+ inputs : this . pins . inputs || [ ] ,
102+ outputs : this . pins . outputs || [ ]
103+ } ,
104+ defaultData : this . defaultData ,
105+ theme : this . theme ,
106+ icon : this . icon ,
107+ graphType : this . graphType ,
108+ isActionNode : this . isActionNode ( )
109+ } ;
110+ }
111+
112+ /**
113+ * Получить пин по ID
114+ * @param {string } pinId - ID пина
115+ * @param {string } direction - 'input' или 'output'
116+ */
117+ getPin ( pinId , direction ) {
118+ const pins = direction === 'input' ? this . pins . inputs : this . pins . outputs ;
119+ return pins . find ( pin => pin . id === pinId ) ;
120+ }
121+
122+ /**
123+ * Проверить, является ли пин обязательным
124+ */
125+ isPinRequired ( pinId , direction = 'input' ) {
126+ const pin = this . getPin ( pinId , direction ) ;
127+ return pin ?. required === true ;
128+ }
129+ }
130+
131+ /**
132+ * Создать определение ноды с билдером
133+ */
134+ function createNodeDefinition ( config ) {
135+ return new NodeDefinition ( config ) ;
136+ }
137+
138+ module . exports = { NodeDefinition, createNodeDefinition } ;
0 commit comments