@pxp-nd/flow 1.1.30 → 1.1.31

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.
@@ -9,7 +9,7 @@
9
9
  * @author Favio Figueroa
10
10
  *
11
11
  * Created at : 2021-07-08 12:55:38
12
- * Last modified :
12
+ * Last modified : 2026-11-06 — Rensi Arteaga — @ApiDoc for OpenAPI (spec 04)
13
13
  */
14
14
  import { EntityManager } from 'typeorm';
15
15
  import { Controller } from '@pxp-nd/core';
@@ -10,7 +10,7 @@
10
10
  * @author Favio Figueroa
11
11
  *
12
12
  * Created at : 2021-07-08 12:55:38
13
- * Last modified :
13
+ * Last modified : 2026-11-06 — Rensi Arteaga — @ApiDoc for OpenAPI (spec 04)
14
14
  */
15
15
  var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
16
16
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
@@ -30,9 +30,13 @@ const core_1 = require("@pxp-nd/core");
30
30
  const Action_1 = __importDefault(require("../entity/Action"));
31
31
  const FieldMap_1 = __importDefault(require("../entity/FieldMap"));
32
32
  const OriginName_1 = __importDefault(require("../entity/OriginName"));
33
+ const FlowNdApiDocs_1 = require("../helpers/FlowNdApiDocs");
33
34
  let Action = class Action extends core_1.Controller {
34
35
  async getFieldMapByAction(params, manager) {
35
36
  const { originName } = params;
37
+ if (originName == null || String(originName).trim() === '') {
38
+ throw new core_1.PxpError(400, 'originName is required');
39
+ }
36
40
  const fieldMapData = await (0, core_1.__)(manager.createQueryBuilder(FieldMap_1.default, 'fm')
37
41
  .innerJoin(OriginName_1.default, 'on', 'on.originNameId = fm.originNameId')
38
42
  .where("on.name = :n ", { n: originName })
@@ -61,8 +65,9 @@ let Action = class Action extends core_1.Controller {
61
65
  __decorate([
62
66
  (0, core_1.Get)(),
63
67
  (0, core_1.DbSettings)('Orm'),
64
- (0, core_1.ReadOnly)(false),
68
+ (0, core_1.ReadOnly)(true),
65
69
  (0, core_1.Log)(true),
70
+ (0, core_1.ApiDoc)(FlowNdApiDocs_1.actionGetFieldMapByActionDoc),
66
71
  __metadata("design:type", Function),
67
72
  __metadata("design:paramtypes", [Object, typeorm_1.EntityManager]),
68
73
  __metadata("design:returntype", Promise)
@@ -72,6 +77,7 @@ __decorate([
72
77
  (0, core_1.DbSettings)('Orm'),
73
78
  (0, core_1.ReadOnly)(true),
74
79
  (0, core_1.Log)(true),
80
+ (0, core_1.ApiDoc)(FlowNdApiDocs_1.actionGetActionsDoc),
75
81
  __metadata("design:type", Function),
76
82
  __metadata("design:paramtypes", [Object, typeorm_1.EntityManager]),
77
83
  __metadata("design:returntype", Promise)
@@ -19,6 +19,7 @@
19
19
  * 28-Sep-2023 SP06OCT23 Mercedes Zambrana Add Validation when change off status (validateFlow, deleteflow, saveFlow, saveflowName)
20
20
  * 07-Feb-2025 8353064698 Mercedes Zambrana Add validation for opt in page when flow si funnel change
21
21
  * 18-Feb-2025 8501163144 Mercedes Zambrana Add publish filter
22
+ * 06-Nov-2026 Rensi Arteaga @ApiDoc for OpenAPI (spec 04)
22
23
  * ******************************************************************************
23
24
  */
24
25
  import { EntityManager } from 'typeorm';
@@ -20,6 +20,7 @@
20
20
  * 28-Sep-2023 SP06OCT23 Mercedes Zambrana Add Validation when change off status (validateFlow, deleteflow, saveFlow, saveflowName)
21
21
  * 07-Feb-2025 8353064698 Mercedes Zambrana Add validation for opt in page when flow si funnel change
22
22
  * 18-Feb-2025 8501163144 Mercedes Zambrana Add publish filter
23
+ * 06-Nov-2026 Rensi Arteaga @ApiDoc for OpenAPI (spec 04)
23
24
  * ******************************************************************************
24
25
  */
25
26
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
@@ -69,8 +70,13 @@ const FlowInstance_1 = __importDefault(require("../entity/FlowInstance"));
69
70
  const Node_2 = __importDefault(require("./Node"));
70
71
  const axios_1 = __importDefault(require("axios"));
71
72
  //import {configFacebookStrategy} from "./passport-facebook";
73
+ const FlowNdApiDocs_1 = require("../helpers/FlowNdApiDocs");
72
74
  let Flow = class Flow extends core_1.Controller {
73
75
  async get(params) {
76
+ const fid = Number(params.flowId);
77
+ if (!Number.isInteger(fid) || fid < 1) {
78
+ throw new core_1.PxpError(400, 'flowId is required and must be a positive integer');
79
+ }
74
80
  const nodes = await Node_1.default.find({ flowId: params.flowId });
75
81
  const restNodes = [];
76
82
  for (let node of nodes) {
@@ -477,6 +483,10 @@ let Flow = class Flow extends core_1.Controller {
477
483
  }
478
484
  async getFlowRender(params) {
479
485
  var _a;
486
+ const fid = Number(params.flowId);
487
+ if (!Number.isInteger(fid) || fid < 1) {
488
+ throw new core_1.PxpError(400, 'flowId is required and must be a positive integer');
489
+ }
480
490
  const flow = await (0, typeorm_1.getManager)().findOne(Flow_1.default, params.flowId);
481
491
  const totalNodes = await (0, typeorm_1.getManager)()
482
492
  .createQueryBuilder(Node_1.default, "n")
@@ -782,6 +792,15 @@ let Flow = class Flow extends core_1.Controller {
782
792
  const filter = (params === null || params === void 0 ? void 0 : params.filter) ? JSON.parse(params === null || params === void 0 ? void 0 : params.filter) : null;
783
793
  const filters = (filter === null || filter === void 0 ? void 0 : filter.items) || [];
784
794
  const logicOperator = ((_a = filter === null || filter === void 0 ? void 0 : filter.logicOperator) === null || _a === void 0 ? void 0 : _a.toUpperCase()) || 'AND';
795
+ const allowedSort = ['flowId', 'name', 'createdAt', 'modifiedAt'];
796
+ const allowedDir = ['ASC', 'DESC'];
797
+ const sortCol = params.sort != null && params.sort !== '' ? String(params.sort) : 'flowId';
798
+ const dirVal = params.dir != null && params.dir !== ''
799
+ ? String(params.dir).toUpperCase()
800
+ : 'ASC';
801
+ if (!allowedSort.includes(sortCol) || !allowedDir.includes(dirVal)) {
802
+ throw new core_1.PxpError(400, 'sort and dir must be allowed values (whitelist for SQL orderBy)');
803
+ }
785
804
  const queryBuilder = await (0, typeorm_1.getManager)()
786
805
  .createQueryBuilder()
787
806
  .select([
@@ -888,7 +907,7 @@ let Flow = class Flow extends core_1.Controller {
888
907
  // Sorting and pagination
889
908
  //queryBuilder.orderBy(`f.${params.sort}`, params.dir).skip(params.start).take(params.limit);
890
909
  // Sorting and pagination
891
- queryBuilder.orderBy(`f.${params.sort}`, params.dir);
910
+ queryBuilder.orderBy(`f.${sortCol}`, dirVal);
892
911
  // Agrega manualmente la cláusula LIMIT y OFFSET
893
912
  queryBuilder.limit(params.limit).offset(params.start);
894
913
  const data = await queryBuilder.getRawMany();
@@ -929,6 +948,15 @@ let Flow = class Flow extends core_1.Controller {
929
948
  const filters = (filter === null || filter === void 0 ? void 0 : filter.items) || [];
930
949
  const logicOperator = ((_a = filter === null || filter === void 0 ? void 0 : filter.logicOperator) === null || _a === void 0 ? void 0 : _a.toUpperCase()) || "AND";
931
950
  const publish = params._publish;
951
+ const allowedSort = ["flowId", "name", "createdAt", "modifiedAt"];
952
+ const allowedDir = ["ASC", "DESC"];
953
+ const sortCol = params.sort != null && params.sort !== "" ? String(params.sort) : "flowId";
954
+ const dirVal = params.dir != null && params.dir !== ""
955
+ ? String(params.dir).toUpperCase()
956
+ : "ASC";
957
+ if (!allowedSort.includes(sortCol) || !allowedDir.includes(dirVal)) {
958
+ throw new core_1.PxpError(400, "sort and dir must be allowed values (whitelist for SQL orderBy)");
959
+ }
932
960
  const queryBuilder = await (0, typeorm_1.getManager)()
933
961
  .createQueryBuilder()
934
962
  .select([
@@ -1040,7 +1068,7 @@ let Flow = class Flow extends core_1.Controller {
1040
1068
  "f.status",
1041
1069
  ]);
1042
1070
  // Ordenamiento y paginación
1043
- queryBuilder.orderBy(`f.${params.sort || "flowId"}`, params.dir || "ASC");
1071
+ queryBuilder.orderBy(`f.${sortCol}`, dirVal);
1044
1072
  queryBuilder.limit(params.limit || 50).offset(params.start || 0);
1045
1073
  // Obtener los datos
1046
1074
  const data = await queryBuilder.getRawMany();
@@ -1117,6 +1145,7 @@ __decorate([
1117
1145
  (0, core_1.DbSettings)('Orm'),
1118
1146
  (0, core_1.ReadOnly)(true),
1119
1147
  (0, core_1.Log)(true),
1148
+ (0, core_1.ApiDoc)(FlowNdApiDocs_1.flowGetDoc),
1120
1149
  __metadata("design:type", Function),
1121
1150
  __metadata("design:paramtypes", [Object]),
1122
1151
  __metadata("design:returntype", Promise)
@@ -1135,6 +1164,7 @@ __decorate([
1135
1164
  (0, core_1.DbSettings)('Orm'),
1136
1165
  (0, core_1.ReadOnly)(false),
1137
1166
  (0, core_1.Log)(true),
1167
+ (0, core_1.ApiDoc)(FlowNdApiDocs_1.flowDeleteFlowDoc),
1138
1168
  __metadata("design:type", Function),
1139
1169
  __metadata("design:paramtypes", [Object, typeorm_1.EntityManager]),
1140
1170
  __metadata("design:returntype", Promise)
@@ -1144,6 +1174,7 @@ __decorate([
1144
1174
  (0, core_1.DbSettings)('Orm'),
1145
1175
  (0, core_1.ReadOnly)(false),
1146
1176
  (0, core_1.Log)(true),
1177
+ (0, core_1.ApiDoc)(FlowNdApiDocs_1.flowSaveFlowNameDoc),
1147
1178
  __metadata("design:type", Function),
1148
1179
  __metadata("design:paramtypes", [Object, typeorm_1.EntityManager]),
1149
1180
  __metadata("design:returntype", Promise)
@@ -1162,6 +1193,7 @@ __decorate([
1162
1193
  (0, core_1.DbSettings)('Orm'),
1163
1194
  (0, core_1.ReadOnly)(false),
1164
1195
  (0, core_1.Log)(true),
1196
+ (0, core_1.ApiDoc)(FlowNdApiDocs_1.flowSaveFlowDoc),
1165
1197
  __metadata("design:type", Function),
1166
1198
  __metadata("design:paramtypes", [Object, typeorm_1.EntityManager]),
1167
1199
  __metadata("design:returntype", Promise)
@@ -1172,6 +1204,7 @@ __decorate([
1172
1204
  (0, core_1.DbSettings)('Orm'),
1173
1205
  (0, core_1.ReadOnly)(true),
1174
1206
  (0, core_1.Log)(true),
1207
+ (0, core_1.ApiDoc)(FlowNdApiDocs_1.flowGetFlowRenderDoc),
1175
1208
  __metadata("design:type", Function),
1176
1209
  __metadata("design:paramtypes", [Object]),
1177
1210
  __metadata("design:returntype", Promise)
@@ -1181,6 +1214,7 @@ __decorate([
1181
1214
  (0, core_1.DbSettings)('Orm'),
1182
1215
  (0, core_1.ReadOnly)(false),
1183
1216
  (0, core_1.Log)(true),
1217
+ (0, core_1.ApiDoc)(FlowNdApiDocs_1.flowInsertEventFlowDoc),
1184
1218
  __metadata("design:type", Function),
1185
1219
  __metadata("design:paramtypes", [Object, typeorm_1.EntityManager]),
1186
1220
  __metadata("design:returntype", Promise)
@@ -1199,6 +1233,7 @@ __decorate([
1199
1233
  (0, core_1.DbSettings)('Orm'),
1200
1234
  (0, core_1.ReadOnly)(false),
1201
1235
  (0, core_1.Log)(true),
1236
+ (0, core_1.ApiDoc)(FlowNdApiDocs_1.flowChangeStatusFlowDoc),
1202
1237
  __metadata("design:type", Function),
1203
1238
  __metadata("design:paramtypes", [Object, typeorm_1.EntityManager]),
1204
1239
  __metadata("design:returntype", Promise)
@@ -1217,6 +1252,7 @@ __decorate([
1217
1252
  (0, core_1.DbSettings)("Orm"),
1218
1253
  (0, core_1.ReadOnly)(true),
1219
1254
  (0, core_1.Log)(true),
1255
+ (0, core_1.ApiDoc)(FlowNdApiDocs_1.flowListTemplatesDoc),
1220
1256
  __metadata("design:type", Function),
1221
1257
  __metadata("design:paramtypes", [Object]),
1222
1258
  __metadata("design:returntype", Promise)
@@ -1231,6 +1267,7 @@ __decorate([
1231
1267
  __metadata("design:returntype", Promise)
1232
1268
  ], Flow.prototype, "changePublishTemplate", null);
1233
1269
  Flow = __decorate([
1270
+ (0, core_1.ApiDocFor)('add', FlowNdApiDocs_1.flowAddDoc),
1234
1271
  (0, core_1.Model)('flow-nd/Flow')
1235
1272
  ], Flow);
1236
1273
  exports.default = Flow;
@@ -10,6 +10,7 @@
10
10
  * 04-Sep-2023 SP08SEP23 Rensi Arteaga add modifiedAt for flows
11
11
  * 29-Sep-2023 SP06OCT23 Mercedes Zambrana Add validation when flow is on
12
12
  * 19-Jan-2025 8201489097 Favio Figueroa Add Controller Validation
13
+ * 06-Nov-2026 Rensi Arteaga @ApiDoc for OpenAPI (spec 04)
13
14
  * ******************************************************************************
14
15
  */
15
16
  import { EntityManager } from 'typeorm';
@@ -11,6 +11,7 @@
11
11
  * 04-Sep-2023 SP08SEP23 Rensi Arteaga add modifiedAt for flows
12
12
  * 29-Sep-2023 SP06OCT23 Mercedes Zambrana Add validation when flow is on
13
13
  * 19-Jan-2025 8201489097 Favio Figueroa Add Controller Validation
14
+ * 06-Nov-2026 Rensi Arteaga @ApiDoc for OpenAPI (spec 04)
14
15
  * ******************************************************************************
15
16
  */
16
17
  var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
@@ -35,6 +36,7 @@ const FieldMap_1 = __importDefault(require("../entity/FieldMap"));
35
36
  const OriginName_1 = __importDefault(require("../entity/OriginName"));
36
37
  const axios_1 = __importDefault(require("axios"));
37
38
  const Flow_1 = __importDefault(require("../entity/Flow"));
39
+ const FlowNdApiDocs_1 = require("../helpers/FlowNdApiDocs");
38
40
  let Node = class Node extends core_1.Controller {
39
41
  async getNodeData(node, dataId, manager) {
40
42
  const { action: { originName, originKey } } = node;
@@ -113,6 +115,10 @@ let Node = class Node extends core_1.Controller {
113
115
  }
114
116
  async getParameterizedNode(params, manager) {
115
117
  lodash_1.default.templateSettings.interpolate = /{{([\s\S]+?)}}/g;
118
+ const nid = Number(params.nodeId);
119
+ if (!Number.isInteger(nid) || nid < 1) {
120
+ throw new core_1.PxpError(400, 'nodeId is required and must be a positive integer');
121
+ }
116
122
  const { nodeId, flowId, substitutionsSchemaJson = {} } = params;
117
123
  const tNodeData = (0, core_1.__)(Node_1.default.findOne(nodeId));
118
124
  const nodeData = await tNodeData;
@@ -298,6 +304,7 @@ __decorate([
298
304
  (0, core_1.DbSettings)('Orm'),
299
305
  (0, core_1.ReadOnly)(false),
300
306
  (0, core_1.Log)(true),
307
+ (0, core_1.ApiDoc)(FlowNdApiDocs_1.nodeAddDoc),
301
308
  __metadata("design:type", Function),
302
309
  __metadata("design:paramtypes", [Object, typeorm_1.EntityManager]),
303
310
  __metadata("design:returntype", Promise)
@@ -307,6 +314,7 @@ __decorate([
307
314
  (0, core_1.DbSettings)('Orm'),
308
315
  (0, core_1.ReadOnly)(false),
309
316
  (0, core_1.Log)(true),
317
+ (0, core_1.ApiDoc)(FlowNdApiDocs_1.nodeAddActionConfigJsonDoc),
310
318
  __metadata("design:type", Function),
311
319
  __metadata("design:paramtypes", [Object, typeorm_1.EntityManager]),
312
320
  __metadata("design:returntype", Promise)
@@ -316,6 +324,7 @@ __decorate([
316
324
  (0, core_1.DbSettings)('Orm'),
317
325
  (0, core_1.ReadOnly)(false),
318
326
  (0, core_1.Log)(true),
327
+ (0, core_1.ApiDoc)(FlowNdApiDocs_1.nodeGetParameterizedNodeDoc),
319
328
  __metadata("design:type", Function),
320
329
  __metadata("design:paramtypes", [Object, typeorm_1.EntityManager]),
321
330
  __metadata("design:returntype", Promise)
@@ -0,0 +1,19 @@
1
+ /**
2
+ * @pxp-nd/flow — OpenAPI (@ApiDoc) payloads for flow-nd controllers (spec tempo-04).
3
+ * Vendor is session-scoped; do not document vendorId / _vendorId as inputs.
4
+ */
5
+ import { ApiDocSpec } from '@pxp-nd/core';
6
+ export declare const flowListTemplatesDoc: ApiDocSpec;
7
+ export declare const flowGetDoc: ApiDocSpec;
8
+ export declare const flowGetFlowRenderDoc: ApiDocSpec;
9
+ export declare const flowAddDoc: ApiDocSpec;
10
+ export declare const flowSaveFlowDoc: ApiDocSpec;
11
+ export declare const flowSaveFlowNameDoc: ApiDocSpec;
12
+ export declare const flowInsertEventFlowDoc: ApiDocSpec;
13
+ export declare const flowChangeStatusFlowDoc: ApiDocSpec;
14
+ export declare const flowDeleteFlowDoc: ApiDocSpec;
15
+ export declare const nodeAddDoc: ApiDocSpec;
16
+ export declare const nodeAddActionConfigJsonDoc: ApiDocSpec;
17
+ export declare const nodeGetParameterizedNodeDoc: ApiDocSpec;
18
+ export declare const actionGetActionsDoc: ApiDocSpec;
19
+ export declare const actionGetFieldMapByActionDoc: ApiDocSpec;
@@ -0,0 +1,299 @@
1
+ "use strict";
2
+ /**
3
+ * @pxp-nd/flow — OpenAPI (@ApiDoc) payloads for flow-nd controllers (spec tempo-04).
4
+ * Vendor is session-scoped; do not document vendorId / _vendorId as inputs.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.actionGetFieldMapByActionDoc = exports.actionGetActionsDoc = exports.nodeGetParameterizedNodeDoc = exports.nodeAddActionConfigJsonDoc = exports.nodeAddDoc = exports.flowDeleteFlowDoc = exports.flowChangeStatusFlowDoc = exports.flowInsertEventFlowDoc = exports.flowSaveFlowNameDoc = exports.flowSaveFlowDoc = exports.flowAddDoc = exports.flowGetFlowRenderDoc = exports.flowGetDoc = exports.flowListTemplatesDoc = void 0;
8
+ exports.flowListTemplatesDoc = {
9
+ operationId: 'flow-nd.Flow.listTemplates',
10
+ summary: 'List templates',
11
+ description: 'Lists templates the session vendor can use: its own and the shared ones. Returns { data, count }. Defaults: _type \'template\', sort \'flowId\', dir \'ASC\', limit 50.',
12
+ params: {
13
+ type: 'object',
14
+ properties: {
15
+ _templateType: { type: 'string', enum: ['flow', 'funnel'] },
16
+ _type: { type: 'string', enum: ['template'] },
17
+ _publish: { type: 'string', enum: ['Y', 'N'], description: 'Y = only published templates.' },
18
+ _isActive: { type: 'integer', enum: [0, 1] },
19
+ genericFilterFields: { type: 'string', enum: ['name', 'description'] },
20
+ genericFilterValue: { type: 'string' },
21
+ filter: { type: 'string', description: 'JSON string { items, logicOperator }, as for the flow list.' },
22
+ start: { type: 'integer', minimum: 0 },
23
+ limit: { type: 'integer', minimum: 1 },
24
+ sort: { type: 'string', enum: ['flowId', 'name', 'createdAt', 'modifiedAt'] },
25
+ dir: { type: 'string', enum: ['ASC', 'DESC'] },
26
+ },
27
+ additionalProperties: false,
28
+ },
29
+ readOnly: true,
30
+ permission: null,
31
+ };
32
+ exports.flowGetDoc = {
33
+ operationId: 'flow-nd.Flow.get',
34
+ summary: 'Nodes of a flow',
35
+ description: 'Returns the nodes of one flow as an array of { node, connections }: connections are the IDs of child nodes, node.valuesForShowingInNode holds the main configured values.',
36
+ params: {
37
+ type: 'object',
38
+ properties: { flowId: { type: 'integer', minimum: 1 } },
39
+ required: ['flowId'],
40
+ additionalProperties: false,
41
+ },
42
+ readOnly: true,
43
+ permission: null,
44
+ };
45
+ exports.flowGetFlowRenderDoc = {
46
+ operationId: 'flow-nd.Flow.getFlowRender',
47
+ summary: 'Editor board of a flow',
48
+ description: 'Returns { flow, board } as used by the flow editor. board.columns[\'2-column-nodes-configured\'].taskIds is the current node order (\'node-<nodeId>\'); board.columns[\'1-column-config-nodes\'].taskIds are the steps that can be added next. Same behaviour for GET and POST.',
49
+ params: {
50
+ type: 'object',
51
+ properties: { flowId: { type: 'integer', minimum: 1 } },
52
+ required: ['flowId'],
53
+ additionalProperties: false,
54
+ },
55
+ readOnly: true,
56
+ permission: null,
57
+ };
58
+ exports.flowAddDoc = {
59
+ operationId: 'flow-nd.Flow.add',
60
+ summary: 'Create a flow',
61
+ description: 'Creates a flow for the session vendor. This is the default create route of the Flow model: it saves the fields it receives. Returns the saved flow row, including flowId.',
62
+ params: {
63
+ type: 'object',
64
+ properties: {
65
+ name: { type: 'string', minLength: 1, maxLength: 255 },
66
+ description: { type: 'string' },
67
+ templateType: { type: 'string', enum: ['flow', 'funnel'] },
68
+ type: { type: 'string', enum: ['custom', 'template'] },
69
+ status: { type: 'string', enum: ['off', 'on'] },
70
+ },
71
+ required: ['name', 'templateType', 'type'],
72
+ additionalProperties: false,
73
+ },
74
+ readOnly: false,
75
+ permission: null,
76
+ };
77
+ exports.flowSaveFlowDoc = {
78
+ operationId: 'flow-nd.Flow.saveFlow',
79
+ summary: 'Add or remove a step',
80
+ description: 'Adds or removes a step in a flow, as the flow editor does. The flow must be off, otherwise 400 \'Please turn off the flow before make a change\'. To add a step (origin \'cloneTask\'): taskIds is the full new order with \'new\' at the position of the new step, and tasks.new holds the flow ID and the action code. To remove a step (origin \'deleteTask\'): taskIds is the order without that node and deleteId is its ID. Other keys of tasks are ignored. Returns { success: true, nodeId } (the new node ID, or null).',
81
+ params: {
82
+ type: 'object',
83
+ properties: {
84
+ board: {
85
+ type: 'object',
86
+ properties: {
87
+ origin: { type: 'string', enum: ['cloneTask', 'deleteTask'] },
88
+ deleteId: { type: 'string', pattern: '^node-[0-9]+$', description: 'Only for deleteTask.' },
89
+ columns: {
90
+ type: 'object',
91
+ properties: {
92
+ '2-column-nodes-configured': {
93
+ type: 'object',
94
+ properties: {
95
+ taskIds: {
96
+ type: 'array',
97
+ items: { type: 'string', pattern: '^(new|node-[0-9]+)$' },
98
+ description: 'Node order. Existing nodes are \'node-<nodeId>\'; for cloneTask \'new\' once.',
99
+ },
100
+ },
101
+ required: ['taskIds'],
102
+ },
103
+ },
104
+ required: ['2-column-nodes-configured'],
105
+ },
106
+ tasks: {
107
+ type: 'object',
108
+ properties: {
109
+ new: {
110
+ type: 'object',
111
+ properties: {
112
+ flowId: { type: 'integer', minimum: 1 },
113
+ action: {
114
+ type: 'object',
115
+ properties: { code: { type: 'string', description: 'Action code from Action/getActions.' } },
116
+ required: ['code'],
117
+ },
118
+ },
119
+ required: ['flowId', 'action'],
120
+ },
121
+ },
122
+ },
123
+ },
124
+ required: ['origin', 'columns'],
125
+ },
126
+ },
127
+ required: ['board'],
128
+ additionalProperties: false,
129
+ },
130
+ readOnly: false,
131
+ permission: null,
132
+ };
133
+ exports.flowSaveFlowNameDoc = {
134
+ operationId: 'flow-nd.Flow.saveFlowName',
135
+ summary: 'Rename a flow',
136
+ description: 'Renames a flow. The flow must be off (400 otherwise). For a template it also saves code, description, icon and flowType. Returns { success: true } or { success: false }.',
137
+ params: {
138
+ type: 'object',
139
+ properties: {
140
+ flowId: { type: 'integer', minimum: 1 },
141
+ name: { type: 'string', minLength: 1, maxLength: 255 },
142
+ code: { type: 'string', description: 'Templates only.' },
143
+ description: { type: 'string', description: 'Templates only.' },
144
+ icon: { type: 'string', description: 'Templates only.' },
145
+ flowType: { type: 'string', description: 'Templates only.' },
146
+ },
147
+ required: ['flowId', 'name'],
148
+ additionalProperties: false,
149
+ },
150
+ readOnly: false,
151
+ permission: null,
152
+ };
153
+ exports.flowInsertEventFlowDoc = {
154
+ operationId: 'flow-nd.Flow.insertEventFlow',
155
+ summary: 'Add the trigger of a flow',
156
+ description: 'Creates the first node (isInit = \'Y\') of a flow from an EVENT action. Returns { success: true, nodeId } or { success: false, msg }.',
157
+ params: {
158
+ type: 'object',
159
+ properties: {
160
+ flowId: { type: 'integer', minimum: 1 },
161
+ actionId: { type: 'integer', minimum: 1, description: 'An active EVENT action (Action/getActions with actionTypeName \'EVENT\').' },
162
+ },
163
+ required: ['flowId', 'actionId'],
164
+ additionalProperties: false,
165
+ },
166
+ readOnly: false,
167
+ permission: null,
168
+ };
169
+ exports.flowChangeStatusFlowDoc = {
170
+ operationId: 'flow-nd.Flow.changeStatusFlow',
171
+ summary: 'Turn a flow on or off',
172
+ description: 'Toggles the flow status between \'off\' and \'on\'. A flow that is on runs for real contacts (sends emails and messages). Turning on needs at least 2 active steps (400 otherwise). Returns { success: true } or { success: false }.',
173
+ params: {
174
+ type: 'object',
175
+ properties: { flowId: { type: 'integer', minimum: 1 } },
176
+ required: ['flowId'],
177
+ additionalProperties: false,
178
+ },
179
+ readOnly: false,
180
+ permission: null,
181
+ };
182
+ exports.flowDeleteFlowDoc = {
183
+ operationId: 'flow-nd.Flow.deleteFlow',
184
+ summary: 'Delete a flow',
185
+ description: 'Soft-deletes a flow: the flow, its instances, nodes and connections become inactive. The flow must be off (400 otherwise). Returns { success: true } or { success: false }.',
186
+ params: {
187
+ type: 'object',
188
+ properties: { flowId: { type: 'integer', minimum: 1 } },
189
+ required: ['flowId'],
190
+ additionalProperties: false,
191
+ },
192
+ readOnly: false,
193
+ permission: null,
194
+ };
195
+ exports.nodeAddDoc = {
196
+ operationId: 'flow-nd.Node.add',
197
+ summary: 'Create a node with parent connections',
198
+ description: 'Creates a node in a flow. For each parent, the parent\'s existing child connections are moved to the new node and a connection parent → new node is added. Every parentId must be a node of the same flow. The flow editor uses Flow/saveFlow instead. Returns the saved node row, including nodeId.',
199
+ params: {
200
+ type: 'object',
201
+ properties: {
202
+ flowId: { type: 'integer', minimum: 1 },
203
+ actionId: { type: 'integer', minimum: 1 },
204
+ isInit: { type: 'string', enum: ['Y', 'N'] },
205
+ isEnd: { type: 'string', enum: ['Y', 'N'] },
206
+ parents: {
207
+ type: 'array',
208
+ items: {
209
+ type: 'object',
210
+ properties: {
211
+ parentId: { type: 'integer', minimum: 1 },
212
+ condition: { type: 'string' },
213
+ },
214
+ required: ['parentId'],
215
+ additionalProperties: false,
216
+ },
217
+ },
218
+ },
219
+ required: ['flowId', 'actionId', 'isInit', 'isEnd'],
220
+ additionalProperties: false,
221
+ },
222
+ readOnly: false,
223
+ permission: null,
224
+ };
225
+ exports.nodeAddActionConfigJsonDoc = {
226
+ operationId: 'flow-nd.Node.AddActionConfigJson',
227
+ summary: 'Save the configuration of a step',
228
+ description: 'Saves the configuration of one node. The flow must be off (400 otherwise). The step fields are sent as top-level keys next to nodeId. __metadata maps a field name to { name } for fields that hold a merge variable; such a field is stored as \'{{ <name> }}\'. The step\'s validation controller runs before saving. Returns { actionConfigJson, success: true, nodeId, msg }.',
229
+ params: {
230
+ type: 'object',
231
+ properties: {
232
+ nodeId: { type: 'integer', minimum: 1 },
233
+ __metadata: {
234
+ type: 'object',
235
+ additionalProperties: {
236
+ type: 'object',
237
+ properties: { name: { type: 'string' } },
238
+ required: ['name'],
239
+ },
240
+ },
241
+ },
242
+ required: ['nodeId', '__metadata'],
243
+ additionalProperties: true,
244
+ },
245
+ readOnly: false,
246
+ permission: null,
247
+ };
248
+ exports.nodeGetParameterizedNodeDoc = {
249
+ operationId: 'flow-nd.Node.getParameterizedNode',
250
+ summary: 'Step with its field schema',
251
+ description: 'Returns a node with what is needed to configure it: the node, its merged current values, schemaJsonObject (the field schema of the step, with substitutions applied) and the merge fields available from the trigger of the flow. Does not change data.',
252
+ params: {
253
+ type: 'object',
254
+ properties: {
255
+ nodeId: { type: 'integer', minimum: 1 },
256
+ substitutionsSchemaJson: {
257
+ type: 'object',
258
+ description: 'Values substituted into the step\'s schema template.',
259
+ properties: {
260
+ locationId: { type: 'integer', minimum: 1 },
261
+ keyword: { type: 'string' },
262
+ },
263
+ additionalProperties: false,
264
+ },
265
+ },
266
+ required: ['nodeId'],
267
+ additionalProperties: false,
268
+ },
269
+ readOnly: true,
270
+ permission: null,
271
+ };
272
+ exports.actionGetActionsDoc = {
273
+ operationId: 'flow-nd.Action.getActions',
274
+ summary: 'Catalog of step types',
275
+ description: 'Returns { data: Action[] }; each action has actionId, code, name, schemaJson (field schema of the step), configJsonTemplate and actionType. Filter by actionTypeName, for example \'EVENT\' for triggers.',
276
+ params: {
277
+ type: 'object',
278
+ properties: {
279
+ actionTypeName: { type: 'string', description: 'For example EVENT, PAGE, CHAINED FLOW.' },
280
+ actionId: { type: 'integer', minimum: 1 },
281
+ },
282
+ additionalProperties: false,
283
+ },
284
+ readOnly: true,
285
+ permission: null,
286
+ };
287
+ exports.actionGetFieldMapByActionDoc = {
288
+ operationId: 'flow-nd.Action.getFieldMapByAction',
289
+ summary: 'Merge fields of an origin',
290
+ description: 'Returns the field-map rows (merge fields) of an origin, the data source of a trigger (Action.originName).',
291
+ params: {
292
+ type: 'object',
293
+ properties: { originName: { type: 'string', minLength: 1 } },
294
+ required: ['originName'],
295
+ additionalProperties: false,
296
+ },
297
+ readOnly: true,
298
+ permission: null,
299
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pxp-nd/flow",
3
- "version": "1.1.30",
3
+ "version": "1.1.31",
4
4
  "description": "Workflow module for pxp-nd framework",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -37,7 +37,7 @@
37
37
  },
38
38
  "dependencies": {
39
39
  "@pxp-nd/common": "^1.1.4",
40
- "@pxp-nd/core": "^1.1.13",
40
+ "@pxp-nd/core": "^1.2.94",
41
41
  "axios": "^0.21.1",
42
42
  "lodash": "^4.17.21",
43
43
  "typeorm": "^0.2.36"