@easyrpa/script-creator 1.0.0

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.
@@ -0,0 +1,32 @@
1
+ import { ExternalDataNodeType, ExternalDataEdgeType, MetaDataType, VariablesNamesType, CollectionType } from "./types";
2
+ export interface IScriptCreator {
3
+ collections: CollectionType[];
4
+ metaData?: MetaDataType;
5
+ isDebugMode?: boolean;
6
+ isRunMode?: boolean;
7
+ createScript(dirPath: string, nodes: ExternalDataNodeType[], edges: ExternalDataEdgeType[], parentNode?: ExternalDataNodeType): Promise<string>;
8
+ }
9
+ export type ScriptCreatorConfig = {
10
+ logDebugVariablesPath?: string;
11
+ metaData?: MetaDataType;
12
+ isDebugMode?: boolean;
13
+ isRunMode?: boolean;
14
+ variablesNames?: Partial<VariablesNamesType>;
15
+ };
16
+ export declare class ScriptCreator implements IScriptCreator {
17
+ collections: CollectionType[];
18
+ metaData?: MetaDataType;
19
+ isDebugMode?: boolean;
20
+ isRunMode?: boolean;
21
+ variablesNames: VariablesNamesType;
22
+ logDebugVariablesPath?: string;
23
+ constructor(collections: CollectionType[], config: ScriptCreatorConfig);
24
+ createScript(dirPath: string, nodes: ExternalDataNodeType[], edges: ExternalDataEdgeType[], parentNode?: ExternalDataNodeType | undefined): Promise<string>;
25
+ private topologicalSorting;
26
+ private getInputVars;
27
+ private getInputVarsForContainer;
28
+ private createScriptContainers;
29
+ private createScriptSubFlows;
30
+ private createCallNodeFunction;
31
+ private createScriptString;
32
+ }
package/dist/index.js ADDED
@@ -0,0 +1,460 @@
1
+ import fsPromises from "fs/promises";
2
+ import path from "path";
3
+ import { HandleTypes, NodeTypes, } from "./types";
4
+ import { getSubFlowName, normalize } from "./utils";
5
+ export class ScriptCreator {
6
+ constructor(collections, config) {
7
+ this.logDebugVariablesPath = config.logDebugVariablesPath;
8
+ this.metaData = config.metaData;
9
+ this.isDebugMode = config.isDebugMode;
10
+ this.isRunMode = config.isRunMode;
11
+ this.variablesNames = {
12
+ nodesVariableName: "nodes",
13
+ containerDataName: "container_data",
14
+ nodesJsonVariableName: "nodes_pickle",
15
+ inputDictName: "input_dict",
16
+ inHandlesName: "in_handles",
17
+ defaultScriptName: "script.py",
18
+ ...(config.variablesNames || {}),
19
+ };
20
+ this.collections = collections;
21
+ }
22
+ //создание директории скрипта по заданному пути
23
+ async createScript(dirPath, nodes, edges, parentNode = undefined) {
24
+ // проверяем наличие всех необходимых блоков
25
+ const allAvailableNodes = this.collections.reduce((allNodes, collection) => {
26
+ return [
27
+ ...allNodes,
28
+ ...collection.nodes
29
+ ];
30
+ }, []);
31
+ const nodesIsAvailable = nodes.every(node => allAvailableNodes.some(avNode => avNode.collection === node.collection && avNode.name === node.name));
32
+ if (!nodesIsAvailable) {
33
+ return Promise.reject('Some nodes are missing from collections');
34
+ }
35
+ // замена пути к директории блока
36
+ nodes.forEach(node => {
37
+ const availableNode = allAvailableNodes.find(avNode => avNode.collection === node.collection && avNode.name === node.name);
38
+ if (availableNode) {
39
+ node.path = availableNode.path;
40
+ }
41
+ });
42
+ // сортировка узлов
43
+ const nodesTree = nodes.filter((node) => !(node.parentsId && node.parentsId.length > 0));
44
+ const nodesSort = this.topologicalSorting(nodesTree, edges);
45
+ // копируем все директории узлов Control и Container
46
+ const uniqueNodes = nodes
47
+ .filter((node) => node.type === NodeTypes.CONTROL || node.type === NodeTypes.CONTAINER)
48
+ .filter((node, index, arr) => arr.findIndex((n) => n.name === node.name) === index);
49
+ for (const node of uniqueNodes) {
50
+ if (node.path && node.scriptPath && node.name) {
51
+ await fsPromises.cp(path.join(node.path, path.dirname(normalize(node.scriptPath))), path.join(dirPath, node.name), { recursive: true });
52
+ }
53
+ else {
54
+ return Promise.reject(`Node ${node.name} incorrect: ${JSON.stringify(node)}`);
55
+ }
56
+ }
57
+ //создаем скрипты для подсхем
58
+ await this.createScriptSubFlows(nodes, dirPath);
59
+ //записываем текст скрипта
60
+ const scriptStr = this.createScriptString(nodes, nodesSort, edges, parentNode);
61
+ const scriptPath = path.join(dirPath, this.variablesNames.defaultScriptName);
62
+ await fsPromises.writeFile(scriptPath, scriptStr);
63
+ return scriptPath;
64
+ }
65
+ //Вспомагательные методы
66
+ //топологическая сортировка узлов одной иерархии
67
+ topologicalSorting(nodes, edges) {
68
+ const nodeTemp = structuredClone(nodes);
69
+ const edgeTemp = structuredClone(edges);
70
+ // Формирование списка опорных узлов, у которых нет входных линий либо входные линии находятся вне его родителя
71
+ const supportNodes = nodeTemp.filter((node) => {
72
+ return !edgeTemp.some((edge) => edge.target === node.id &&
73
+ nodeTemp.some((sourceNode) => sourceNode.id === edge.source));
74
+ });
75
+ // Топологическая сортировка (с помощью обхода в глубину)
76
+ const grayStack = [];
77
+ const blackStack = [];
78
+ supportNodes.forEach((supportNode) => {
79
+ //Помещаем опорный узел в стек Gray
80
+ grayStack.push(supportNode);
81
+ //Поиск в глубину по узлам из стека Gray
82
+ let n = 0;
83
+ while (grayStack.length) {
84
+ const firstNode = grayStack[n];
85
+ if (firstNode) {
86
+ //помещаем соседний узел в стек Gray
87
+ const nextEdge = edgeTemp.find((edge) => !edge.visited && edge.source === firstNode.id);
88
+ if (nextEdge) {
89
+ nextEdge.visited = true;
90
+ const nextNode = nodeTemp.find((node) => node.id === nextEdge.target);
91
+ if (nextNode) {
92
+ if (blackStack.find((node) => node.id === nextNode.id) ||
93
+ grayStack.find((node) => node.id === nextNode.id)) {
94
+ n -= 1; // для перехода к этому же узлу
95
+ }
96
+ else {
97
+ grayStack.push(nextNode);
98
+ }
99
+ }
100
+ else {
101
+ n -= 1; // для перехода к этому же узлу
102
+ }
103
+ }
104
+ else {
105
+ // Если это тупик, то помещаем firstNode в стек Black
106
+ blackStack.push(firstNode);
107
+ grayStack.splice(n, 1); // и удаляем firstNode из стека Gray
108
+ n -= 2; // для перехода к предыдущему узлу
109
+ }
110
+ }
111
+ n++;
112
+ }
113
+ });
114
+ return blackStack.reverse();
115
+ }
116
+ //получение строки входных параметров функций узлов
117
+ getInputVars(node) {
118
+ const inputVarsArray = [];
119
+ //данные родительских контейнеров
120
+ const isChild = node.parentsId?.length && node.parentsId.length > 0 ? true : false;
121
+ isChild &&
122
+ inputVarsArray.push(`"parent_data": ${this.variablesNames.containerDataName}`);
123
+ //данные из линий, входящих в дескрипторы (переменные), или данные из настроек узла (текстовые константы)
124
+ let inputHandlesVars = [];
125
+ if (node.inputHandles && node.inputHandles.length !== 0) {
126
+ inputHandlesVars = node.inputHandles.reduce((result, handle) => {
127
+ if (handle.hidden) {
128
+ //указание константы из настроек узла
129
+ return [
130
+ ...result,
131
+ `"${handle.name}": ${handle.value ? `"${handle.value}"` : "None"}`,
132
+ ];
133
+ }
134
+ else {
135
+ if (handle.connectedEdges && handle.connectedEdges.length !== 0) {
136
+ //указание переменной выходного узла связанной линии
137
+ return [
138
+ ...result,
139
+ ...handle.connectedEdges
140
+ .filter((edge) => !edge.isReplacement)
141
+ .map((edge) => `"${handle.name}": ${this.variablesNames.nodesVariableName}["out_handles_${edge.sourceCid}"]["${edge.sourceHandle}"]`),
142
+ ];
143
+ }
144
+ else {
145
+ //указание None
146
+ return [...result, `"${handle.name}": None`];
147
+ }
148
+ }
149
+ }, []);
150
+ }
151
+ inputVarsArray.push(`"${this.variablesNames.inHandlesName}": {${inputHandlesVars?.length > 0 ? inputHandlesVars.join(",") : ""}}`);
152
+ const contentValues = `"content_values": ${node.contentValues && Object.keys(node.contentValues).length > 0
153
+ ? JSON.stringify(node.contentValues)
154
+ : "{}"}`;
155
+ contentValues && inputVarsArray.push(contentValues);
156
+ //лямбда функция дочерних блоков контейнеров
157
+ let containerVars = "";
158
+ if (node.type === NodeTypes.CONTAINER) {
159
+ containerVars = this.getInputVarsForContainer(node, isChild);
160
+ }
161
+ containerVars && inputVarsArray.push(containerVars);
162
+ //мета-данные
163
+ if (this.metaData) {
164
+ const metaDataVars = `"meta_data": {${Object.entries(this.metaData)
165
+ .map(([key, value]) => `"${key}": "${value}"`)
166
+ .join(",")}}`;
167
+ inputVarsArray.push(metaDataVars);
168
+ }
169
+ //данные блока
170
+ if (node.cid) {
171
+ const nodeData = {
172
+ id: node.cid,
173
+ };
174
+ const nodeDataVars = `"node_data": {${Object.entries(nodeData)
175
+ .map(([key, value]) => `"${key}": "${value}"`)
176
+ .join(",")}}`;
177
+ inputVarsArray.push(nodeDataVars);
178
+ }
179
+ return `{${inputVarsArray.join(",")}}`;
180
+ }
181
+ //получение строки входных параметров функций контейнеров
182
+ getInputVarsForContainer(container, isChild) {
183
+ const containerData = `{${isChild ? `**${this.variablesNames.containerDataName}, ` : ""}**data}`;
184
+ return `"children": lambda data={}: ${container.cid}_children(${this.variablesNames.nodesVariableName},${containerData})`;
185
+ }
186
+ //создание функции контейнера
187
+ createScriptContainers(nodes, edges, mainScriptArray) {
188
+ nodes
189
+ .filter((node) => node.type === NodeTypes.CONTAINER)
190
+ .forEach((container) => {
191
+ //название функции
192
+ mainScriptArray.push(`def ${container.cid}_children(${this.variablesNames.nodesVariableName}, ${this.variablesNames.containerDataName}):`);
193
+ //входные переменные
194
+ //данные выходных терминалов
195
+ const outputStateTerminals = container.stateTerminals?.filter((terminal) => terminal.handlesType === HandleTypes.OUTPUT) || [];
196
+ if (outputStateTerminals.length > 0) {
197
+ mainScriptArray.push("\t# data output terminals");
198
+ outputStateTerminals.forEach((terminal) => {
199
+ const terminalOutHandles = terminal.outputHandles?.map((handle) => `"${handle.name}": ${this.variablesNames.containerDataName}["${handle.name}"]`) || [];
200
+ mainScriptArray.push(`\t${this.variablesNames.nodesVariableName}["out_handles_${terminal.cid}"] = {${terminalOutHandles.join(",")}}`);
201
+ });
202
+ }
203
+ //функции дочерних узлов
204
+ if (container.children) {
205
+ mainScriptArray.push("\t# functions children nodes");
206
+ const childrenSort = this.topologicalSorting(container.children, edges);
207
+ childrenSort.forEach((child) => {
208
+ this.createCallNodeFunction(child, nodes, mainScriptArray);
209
+ });
210
+ }
211
+ //данные входных терминалов
212
+ const inputStateTerminals = container.stateTerminals?.filter((terminal) => terminal.handlesType === HandleTypes.INPUT) || [];
213
+ if (inputStateTerminals.length > 0) {
214
+ mainScriptArray.push("\t# data input terminals");
215
+ inputStateTerminals.forEach((terminal) => {
216
+ let inputHandlesVars = [];
217
+ if (terminal.inputHandles && terminal.inputHandles.length !== 0) {
218
+ inputHandlesVars = terminal.inputHandles.map((handle) => {
219
+ const edge = handle.connectedEdges && handle.connectedEdges.length > 0
220
+ ? handle.connectedEdges[0]
221
+ : null;
222
+ return `"${handle.name}": ${edge
223
+ ? `${this.variablesNames.nodesVariableName}["out_handles_${edge.sourceCid}"]["${edge.sourceHandle}"]`
224
+ : "None"}`;
225
+ });
226
+ }
227
+ inputHandlesVars.length > 0 &&
228
+ mainScriptArray.push(`\t${this.variablesNames.nodesVariableName}["out_handles_${terminal.cid}"] = {${inputHandlesVars.join(",")}}`);
229
+ });
230
+ }
231
+ //выходные переменные
232
+ const dataInputStateTerminals = inputStateTerminals.reduce((result, terminal) => {
233
+ return [
234
+ ...result,
235
+ ...(terminal.inputHandles?.map((handle) => `"${handle.name}": ${this.variablesNames.nodesVariableName}["out_handles_${terminal.cid}"]["${handle.name}"]`) || []),
236
+ ];
237
+ }, []);
238
+ mainScriptArray.push(`\treturn {${dataInputStateTerminals.join(",")}}`);
239
+ });
240
+ }
241
+ //создание функции подсхемы
242
+ async createScriptSubFlows(nodes, dirPath) {
243
+ const subFlows = nodes.filter((node) => node.type === NodeTypes.SUBFLOW);
244
+ for (const subFlow of subFlows) {
245
+ if (subFlow.dataSubFlow) {
246
+ const dirName = getSubFlowName(subFlow);
247
+ //создаем директорию блока подсхемы
248
+ await fsPromises.mkdir(path.join(dirPath, dirName));
249
+ //создаем скрипт
250
+ await this.createScript(path.join(dirPath, dirName), subFlow.dataSubFlow.nodes, subFlow.dataSubFlow.edges, subFlow);
251
+ }
252
+ }
253
+ }
254
+ //создание строки вызова функции узла
255
+ createCallNodeFunction(node, nodes, resultArray, parentNode = undefined) {
256
+ const nodeName = node.type === NodeTypes.SUBFLOW ? getSubFlowName(node) : node.name;
257
+ let functionCallString = "";
258
+ if (node.type !== NodeTypes.EXTERNALSTATETERMINAL) {
259
+ functionCallString = `\t${this.variablesNames.nodesVariableName}["out_handles_${node.cid}"] = main_${nodeName}(${this.getInputVars(node)})`;
260
+ }
261
+ else {
262
+ //для внешних терминалов входных портов блок схемы
263
+ let handleValues = "";
264
+ if (parentNode) {
265
+ handleValues = [
266
+ ...(node.outputHandles?.map((handle) => {
267
+ //поиск порта у родительского узла
268
+ const parentHandle = parentNode.inputHandles?.find((parentHandle) => {
269
+ if (parentHandle.dataHandleSubFlowTerminal) {
270
+ if (handle.nodeСid ===
271
+ parentHandle.dataHandleSubFlowTerminal.nodeСid) {
272
+ return (handle.name ===
273
+ parentHandle.dataHandleSubFlowTerminal.name);
274
+ }
275
+ }
276
+ return false;
277
+ });
278
+ if (parentHandle) {
279
+ return `"${handle.name}": ${this.variablesNames.inputDictName}["${this.variablesNames.inHandlesName}"]["${parentHandle.name}"]`;
280
+ }
281
+ return `${handle.name}: None`;
282
+ }) || []),
283
+ ...(node.inputHandles?.map((handle) => {
284
+ if (handle.connectedEdges && handle.connectedEdges.length !== 0) {
285
+ //указание переменной выходного узла связанной линии
286
+ const connectedEdge = handle.connectedEdges.find((edge) => !edge.isReplacement);
287
+ if (connectedEdge) {
288
+ return `"${handle.name}": ${this.variablesNames.nodesVariableName}["out_handles_${connectedEdge.sourceCid}"]["${connectedEdge.sourceHandle}"]`;
289
+ }
290
+ }
291
+ return `"${handle.name}": None`;
292
+ }) || []),
293
+ ].join(",");
294
+ }
295
+ else {
296
+ handleValues = [
297
+ ...(node.outputHandles || []),
298
+ ...(node.inputHandles || []),
299
+ ]
300
+ .map((handle) => `"${handle.name}": None`)
301
+ .join(",");
302
+ }
303
+ functionCallString = `\t${this.variablesNames.nodesVariableName}["out_handles_${node.cid}"] = { ${handleValues} }`;
304
+ }
305
+ //формирование списка входящих линий
306
+ const inputEdges = [
307
+ ...(node.connectedEdges || []),
308
+ ...(node.inputHandles || []).reduce((edges, handle) => {
309
+ return [...edges, ...(handle.connectedEdges || [])];
310
+ }, []),
311
+ ];
312
+ if (inputEdges.length > 0) {
313
+ const sourceVariables = [];
314
+ for (const edge of inputEdges) {
315
+ const sourceNode = nodes.find((node) => node.id === edge.source);
316
+ if (sourceNode) {
317
+ if (edge.sourceHandle && sourceNode.outputHandles) {
318
+ const sourceHandle = sourceNode.outputHandles.find((handle) => handle.name === edge.sourceHandle);
319
+ if (sourceHandle) {
320
+ sourceVariables.push(`${this.variablesNames.nodesVariableName}["out_handles_${edge.sourceCid}"] and ${this.variablesNames.nodesVariableName}["out_handles_${edge.sourceCid}"]["${edge.sourceHandle}"]`);
321
+ }
322
+ }
323
+ else {
324
+ sourceVariables.push(`${this.variablesNames.nodesVariableName}["out_handles_${edge.sourceCid}"]`);
325
+ }
326
+ }
327
+ }
328
+ if (sourceVariables.length > 0) {
329
+ const outHandlesStopString = node.outputHandles && node.outputHandles.length > 0
330
+ ? `{${node.outputHandles
331
+ .map((handle) => `"${handle.name}": StopObject()`)
332
+ .join(",")}}`
333
+ : "StopObject()";
334
+ resultArray.push(`\tif any(isinstance(x, StopObject) for x in [${sourceVariables.join(",")}]):`);
335
+ resultArray.push(`\t\t${this.variablesNames.nodesVariableName}["out_handles_${node.cid}"] = ${outHandlesStopString}`);
336
+ resultArray.push(`\telse:`);
337
+ resultArray.push(`\t${functionCallString}`);
338
+ }
339
+ else {
340
+ resultArray.push(functionCallString);
341
+ }
342
+ }
343
+ else {
344
+ resultArray.push(functionCallString);
345
+ }
346
+ const foundNode = nodes.find((fnode) => fnode.cid === node.cid);
347
+ if (foundNode) {
348
+ foundNode.scriptLineNumber = resultArray.length;
349
+ }
350
+ this.isDebugMode &&
351
+ resultArray.push(`\tlog_debug_variables(${this.variablesNames.nodesVariableName})`);
352
+ }
353
+ //создание текста скрипта
354
+ createScriptString(nodes, nodesSort, edges, parentNode) {
355
+ const resultArray = [];
356
+ //дополнение sys.path
357
+ resultArray.push("# add script directory in sys.path");
358
+ resultArray.push("import sys");
359
+ resultArray.push("import os");
360
+ resultArray.push("sys.path.extend([d[0] for d in list(os.walk(os.path.dirname(__file__)))])");
361
+ resultArray.push("sys.stdout.reconfigure(encoding='utf-8')");
362
+ //импорт для отладки
363
+ if ((this.isDebugMode || this.isRunMode) && this.logDebugVariablesPath) {
364
+ resultArray.push("import jsonpickle");
365
+ resultArray.push("def log_debug_variables (variables):");
366
+ resultArray.push("\tdef fail_safe_func(err):");
367
+ resultArray.push("\t\treturn f'Unknown type'");
368
+ resultArray.push(`\tvariables_pickle = jsonpickle.encode(variables, unpicklable=False, fail_safe=fail_safe_func)`);
369
+ resultArray.push(`\twith open(${JSON.stringify(this.logDebugVariablesPath)}, "w") as file:`);
370
+ resultArray.push("\t\tfile.write(variables_pickle)");
371
+ }
372
+ //импорт внутренних классов для формирования скриптов
373
+ resultArray.push("from easy_module import StopObject");
374
+ //формирование основного тела скрипта
375
+ const nodesAndTerminals = [
376
+ ...nodes,
377
+ ...nodes
378
+ .filter((node) => node.type === NodeTypes.CONTAINER)
379
+ .reduce((terminals, container) => {
380
+ return [...terminals, ...(container.stateTerminals || [])];
381
+ }, []),
382
+ ];
383
+ // Комментарий # import nodes functions
384
+ resultArray.push("# import nodes functions");
385
+ // Импорты скриптов узлов
386
+ const importsNodesFunctions = nodes
387
+ .filter((node) => (node.type === NodeTypes.CONTROL ||
388
+ node.type === NodeTypes.CONTAINER) &&
389
+ node.scriptPath !== undefined &&
390
+ node.name !== undefined)
391
+ .filter((node, index, arr) => arr.findIndex((n) => n.name === node.name) === index)
392
+ .map((node) => `from ${node.name}.${path.basename(normalize(node.scriptPath), ".py")} import main as main_${node.name}`);
393
+ resultArray.push(...importsNodesFunctions);
394
+ //импорт скриптов подсхем
395
+ const importsSubFlowFunctions = nodes
396
+ .filter((node) => node.type === NodeTypes.SUBFLOW)
397
+ .map((subFlow) => `from ${subFlow.name}_${subFlow.cid}.${path.basename(this.variablesNames.defaultScriptName || "script", ".py")} import main as main_${subFlow.name}_${subFlow.cid}`);
398
+ resultArray.push(...importsSubFlowFunctions);
399
+ // Комментарий # container functions
400
+ resultArray.push("# container functions");
401
+ // Описание функций контейнеров с дочерними узлами
402
+ this.createScriptContainers(nodes, edges, resultArray);
403
+ // Комментарий # main function
404
+ resultArray.push("# main function");
405
+ // Описание функции main
406
+ resultArray.push(`def main(${this.variablesNames.inputDictName}=None):`);
407
+ // Комментарий # nodes variables
408
+ resultArray.push("\t# nodes variables");
409
+ // Переменные блоков
410
+ const nodesVariables = nodesAndTerminals.map((node) => `"out_handles_${node.cid}": None`);
411
+ resultArray.push(`\t${this.variablesNames.nodesVariableName} = {${nodesVariables.join(",")}}`);
412
+ // Описание функций узлов первой иерархии
413
+ resultArray.push("\t# functions nodes");
414
+ nodesSort.forEach((node) => {
415
+ //строка функции узла
416
+ this.createCallNodeFunction(node, nodes, resultArray, parentNode);
417
+ });
418
+ //запись файла с переменными для режима Run
419
+ this.isRunMode &&
420
+ resultArray.push(`\tlog_debug_variables(${this.variablesNames.nodesVariableName})`);
421
+ //возврат портов выходных внешних терминалов
422
+ if (parentNode) {
423
+ const returnedHandlesValues = nodes
424
+ .filter((node) => node.type === NodeTypes.EXTERNALSTATETERMINAL)
425
+ .reduce((returnedValues, terminal) => {
426
+ return [
427
+ ...returnedValues,
428
+ ...(terminal.inputHandles
429
+ ?.map((handle) => {
430
+ //поиск порта у родительского узла
431
+ const parentHandle = parentNode.outputHandles?.find((parentHandle) => {
432
+ if (parentHandle.dataHandleSubFlowTerminal) {
433
+ if (handle.nodeСid ===
434
+ parentHandle.dataHandleSubFlowTerminal.nodeСid) {
435
+ return (handle.name ===
436
+ parentHandle.dataHandleSubFlowTerminal.name);
437
+ }
438
+ }
439
+ return false;
440
+ });
441
+ if (parentHandle) {
442
+ return `"${parentHandle.name}": ${this.variablesNames.nodesVariableName}["out_handles_${terminal.cid}"]["${handle.name}"]`;
443
+ }
444
+ return;
445
+ })
446
+ .filter((value) => value !== undefined) || []),
447
+ ];
448
+ }, []);
449
+ if (returnedHandlesValues.length > 0) {
450
+ resultArray.push(`\treturn { ${returnedHandlesValues.join(",")} }`);
451
+ }
452
+ }
453
+ // Комментарий # run main function
454
+ resultArray.push("# run main function");
455
+ // Строка запуска функции main
456
+ resultArray.push(`if __name__ == "__main__":`);
457
+ resultArray.push(`\tmain()`);
458
+ return resultArray.join("\n");
459
+ }
460
+ }
@@ -0,0 +1,87 @@
1
+ export type CollectionType = {
2
+ name: string;
3
+ nodes: ExternalDataNodeType[];
4
+ };
5
+ export type ExternalDataNodeType = {
6
+ name: string;
7
+ label: {
8
+ ru: string;
9
+ en: string;
10
+ };
11
+ collection: string;
12
+ cid: string;
13
+ parentsId: string[];
14
+ type: NodeTypes;
15
+ path: string;
16
+ scriptPath: string;
17
+ id: string;
18
+ inputHandles: ExternalDataHandleType[];
19
+ outputHandles: ExternalDataHandleType[];
20
+ stateTerminals: ExternalDataStateTerminalType[];
21
+ connectedEdges: ExternalDataEdgeType[];
22
+ contentValues?: ContentValuesType;
23
+ children?: ExternalDataNodeType[];
24
+ dataSubFlow?: ExternalDataDefaultFlowType;
25
+ scriptLineNumber?: number;
26
+ };
27
+ export type ExternalDataDefaultFlowType = {
28
+ nodes: ExternalDataNodeType[];
29
+ edges: ExternalDataEdgeType[];
30
+ };
31
+ export type ContentValuesType = {
32
+ [key: string]: string | number | {
33
+ [key: string]: string | number;
34
+ } | (string | number)[];
35
+ };
36
+ export type ExternalDataEdgeType = {
37
+ target: string;
38
+ targetCid: string;
39
+ targetHandle?: string;
40
+ source: string;
41
+ sourceCid: string;
42
+ sourceHandle?: string;
43
+ isReplacement: boolean;
44
+ };
45
+ export type ExternalDataStateTerminalType = {
46
+ inputHandles: ExternalDataHandleType[];
47
+ outputHandles: ExternalDataHandleType[];
48
+ handlesType: HandleTypes;
49
+ cid: string;
50
+ };
51
+ export type ExternalDataHandleType = {
52
+ name: string;
53
+ hidden: boolean;
54
+ value: string;
55
+ connectedEdges: ExternalDataEdgeType[];
56
+ dataHandleSubFlowTerminal?: ExternalDataHandleType;
57
+ nodeСid: string;
58
+ };
59
+ export declare enum HandleTypes {
60
+ INPUT = "input",
61
+ OUTPUT = "output"
62
+ }
63
+ export declare enum NodeTypes {
64
+ CONTROL = "control",
65
+ CONTAINER = "container",
66
+ STATETERMINAL = "stateTerminal",
67
+ SUBFLOW = "subFlow",
68
+ EXTERNALSTATETERMINAL = "externalStateTerminal"
69
+ }
70
+ export declare enum LanguageNames {
71
+ RU = "ru",
72
+ EN = "en"
73
+ }
74
+ export type VariablesNamesType = {
75
+ nodesVariableName: string;
76
+ containerDataName: string;
77
+ nodesJsonVariableName: string;
78
+ inputDictName: string;
79
+ inHandlesName: string;
80
+ defaultScriptName: string;
81
+ };
82
+ export type MetaDataType = {
83
+ appLanguage?: LanguageNames;
84
+ };
85
+ export type EdgeSortedType = ExternalDataEdgeType & {
86
+ visited?: boolean;
87
+ };
package/dist/types.js ADDED
@@ -0,0 +1,19 @@
1
+ export var HandleTypes;
2
+ (function (HandleTypes) {
3
+ HandleTypes["INPUT"] = "input";
4
+ HandleTypes["OUTPUT"] = "output";
5
+ })(HandleTypes || (HandleTypes = {}));
6
+ export var NodeTypes;
7
+ (function (NodeTypes) {
8
+ NodeTypes["CONTROL"] = "control";
9
+ NodeTypes["CONTAINER"] = "container";
10
+ NodeTypes["STATETERMINAL"] = "stateTerminal";
11
+ NodeTypes["SUBFLOW"] = "subFlow";
12
+ NodeTypes["EXTERNALSTATETERMINAL"] = "externalStateTerminal";
13
+ })(NodeTypes || (NodeTypes = {}));
14
+ export var LanguageNames;
15
+ (function (LanguageNames) {
16
+ LanguageNames["RU"] = "ru";
17
+ LanguageNames["EN"] = "en";
18
+ })(LanguageNames || (LanguageNames = {}));
19
+ ;
@@ -0,0 +1,3 @@
1
+ import { ExternalDataNodeType } from "./types";
2
+ export declare const getSubFlowName: (subFlow: ExternalDataNodeType) => string;
3
+ export declare const normalize: (p: string) => string;
package/dist/utils.js ADDED
@@ -0,0 +1,8 @@
1
+ import path from 'path';
2
+ //получение имени SubFLow
3
+ export const getSubFlowName = (subFlow) => {
4
+ return `${subFlow.name}_${subFlow.cid}`;
5
+ };
6
+ export const normalize = (p) => {
7
+ return path.normalize(p.replaceAll('\\', '/'));
8
+ };
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "@easyrpa/script-creator",
3
+ "description": "Pyton script creator for easy rpa",
4
+ "version": "1.0.0",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "type": "module",
8
+ "scripts": {
9
+ "test": "echo \"Error: no test specified\" && exit 1",
10
+ "build": "tsc"
11
+ },
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "git+https://github.com/trufak/-easyrpa-script-creator.git"
15
+ },
16
+ "author": "trufak",
17
+ "license": "ISC",
18
+ "bugs": {
19
+ "url": "https://github.com/trufak/-easyrpa-script-creator/issues"
20
+ },
21
+ "homepage": "https://github.com/trufak/-easyrpa-script-creator#readme",
22
+ "private": false,
23
+ "keywords": [
24
+ "easyrpa",
25
+ "script"
26
+ ],
27
+ "devDependencies": {
28
+ "@types/node": "^25.3.0"
29
+ },
30
+ "files": ["dist", "package.json"]
31
+ }