snow-flow 10.0.1-dev.451 → 10.0.1-dev.453
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.
package/package.json
CHANGED
|
@@ -72,6 +72,10 @@ async function executeFlowPatchMutation(
|
|
|
72
72
|
return resp.data?.data?.global?.snFlowDesigner?.flow || resp.data;
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
+
/** Safely extract a string from a ServiceNow Table API value (handles reference objects like {value, link}). */
|
|
76
|
+
const str = (val: any): string =>
|
|
77
|
+
typeof val === 'object' && val !== null ? (val.display_value || val.value || '') : (val || '');
|
|
78
|
+
|
|
75
79
|
// Type label mapping for parameter definitions
|
|
76
80
|
const TYPE_LABELS: Record<string, string> = {
|
|
77
81
|
string: 'String', integer: 'Integer', boolean: 'True/False', choice: 'Choice',
|
|
@@ -106,56 +110,59 @@ async function buildActionInputsForInsert(
|
|
|
106
110
|
// Fuzzy-match user-provided values to actual field names
|
|
107
111
|
var resolvedInputs: Record<string, string> = {};
|
|
108
112
|
if (userValues) {
|
|
109
|
-
var paramElements = actionParams.map(function (p: any) { return p.element; });
|
|
113
|
+
var paramElements = actionParams.map(function (p: any) { return str(p.element); });
|
|
110
114
|
for (var [key, value] of Object.entries(userValues)) {
|
|
111
115
|
if (paramElements.includes(key)) {
|
|
112
116
|
resolvedInputs[key] = value;
|
|
113
117
|
continue;
|
|
114
118
|
}
|
|
115
119
|
var match = actionParams.find(function (p: any) {
|
|
116
|
-
|
|
120
|
+
var el = str(p.element);
|
|
121
|
+
return el.endsWith('_' + key) || el === key || str(p.label).toLowerCase() === key.toLowerCase();
|
|
117
122
|
});
|
|
118
|
-
if (match) resolvedInputs[match.element] = value;
|
|
123
|
+
if (match) resolvedInputs[str(match.element)] = value;
|
|
119
124
|
else resolvedInputs[key] = value;
|
|
120
125
|
}
|
|
121
126
|
}
|
|
122
127
|
|
|
123
128
|
// Build full input objects with parameter definitions (matching UI format)
|
|
129
|
+
// Use str() on all fields — the Table API may return reference fields as objects {value, link}
|
|
124
130
|
var inputs = actionParams.map(function (rec: any) {
|
|
125
|
-
var paramType = rec.internal_type || 'string';
|
|
126
|
-
var
|
|
131
|
+
var paramType = str(rec.internal_type) || 'string';
|
|
132
|
+
var element = str(rec.element);
|
|
133
|
+
var userVal = resolvedInputs[element] || '';
|
|
127
134
|
return {
|
|
128
|
-
id: rec.sys_id,
|
|
129
|
-
name:
|
|
135
|
+
id: str(rec.sys_id),
|
|
136
|
+
name: element,
|
|
130
137
|
children: [],
|
|
131
138
|
displayValue: { value: '' },
|
|
132
139
|
value: { schemaless: false, schemalessValue: '', value: userVal },
|
|
133
140
|
parameter: {
|
|
134
|
-
id: rec.sys_id,
|
|
135
|
-
label: rec.label ||
|
|
136
|
-
name:
|
|
141
|
+
id: str(rec.sys_id),
|
|
142
|
+
label: str(rec.label) || element,
|
|
143
|
+
name: element,
|
|
137
144
|
type: paramType,
|
|
138
145
|
type_label: TYPE_LABELS[paramType] || paramType.charAt(0).toUpperCase() + paramType.slice(1),
|
|
139
|
-
hint: rec.hint
|
|
140
|
-
order: parseInt(rec.order || '0', 10),
|
|
141
|
-
extended: rec.extended === 'true',
|
|
142
|
-
mandatory: rec.mandatory === 'true',
|
|
143
|
-
readonly: rec.read_only === 'true',
|
|
144
|
-
maxsize: parseInt(rec.max_length || '8000', 10),
|
|
145
|
-
data_structure: rec.data_structure
|
|
146
|
-
reference: rec.reference
|
|
147
|
-
reference_display: rec.reference_display
|
|
148
|
-
ref_qual: rec.ref_qual
|
|
149
|
-
choiceOption: rec.choice_option
|
|
150
|
-
table: rec.table_name
|
|
151
|
-
columnName: rec.column_name
|
|
152
|
-
defaultValue: rec.default_value
|
|
153
|
-
use_dependent: rec.use_dependent === 'true',
|
|
154
|
-
dependent_on: rec.dependent_on
|
|
155
|
-
show_ref_finder: rec.show_ref_finder === 'true',
|
|
156
|
-
local: rec.local === 'true',
|
|
157
|
-
attributes: rec.attributes
|
|
158
|
-
sys_class_name: rec.sys_class_name
|
|
146
|
+
hint: str(rec.hint),
|
|
147
|
+
order: parseInt(str(rec.order) || '0', 10),
|
|
148
|
+
extended: str(rec.extended) === 'true',
|
|
149
|
+
mandatory: str(rec.mandatory) === 'true',
|
|
150
|
+
readonly: str(rec.read_only) === 'true',
|
|
151
|
+
maxsize: parseInt(str(rec.max_length) || '8000', 10),
|
|
152
|
+
data_structure: str(rec.data_structure),
|
|
153
|
+
reference: str(rec.reference),
|
|
154
|
+
reference_display: str(rec.reference_display),
|
|
155
|
+
ref_qual: str(rec.ref_qual),
|
|
156
|
+
choiceOption: str(rec.choice_option),
|
|
157
|
+
table: str(rec.table_name),
|
|
158
|
+
columnName: str(rec.column_name),
|
|
159
|
+
defaultValue: str(rec.default_value),
|
|
160
|
+
use_dependent: str(rec.use_dependent) === 'true',
|
|
161
|
+
dependent_on: str(rec.dependent_on),
|
|
162
|
+
show_ref_finder: str(rec.show_ref_finder) === 'true',
|
|
163
|
+
local: str(rec.local) === 'true',
|
|
164
|
+
attributes: str(rec.attributes),
|
|
165
|
+
sys_class_name: str(rec.sys_class_name),
|
|
159
166
|
children: []
|
|
160
167
|
}
|
|
161
168
|
};
|
|
@@ -188,8 +195,8 @@ async function findElementsToReorder(
|
|
|
188
195
|
}
|
|
189
196
|
});
|
|
190
197
|
for (var rec of (resp.data.result || [])) {
|
|
191
|
-
var uuid = rec.ui_unique_identifier;
|
|
192
|
-
var curOrder = parseInt(rec.order || '0', 10);
|
|
198
|
+
var uuid = str(rec.ui_unique_identifier);
|
|
199
|
+
var curOrder = parseInt(str(rec.order) || '0', 10);
|
|
193
200
|
if (uuid && curOrder >= targetOrder) {
|
|
194
201
|
flowLogicUpdates.push({ order: String(curOrder + 1), uiUniqueIdentifier: uuid, type: 'flowlogic' });
|
|
195
202
|
}
|
|
@@ -206,8 +213,8 @@ async function findElementsToReorder(
|
|
|
206
213
|
}
|
|
207
214
|
});
|
|
208
215
|
for (var rec2 of (resp2.data.result || [])) {
|
|
209
|
-
var uuid2 = rec2.ui_unique_identifier;
|
|
210
|
-
var curOrder2 = parseInt(rec2.order || '0', 10);
|
|
216
|
+
var uuid2 = str(rec2.ui_unique_identifier);
|
|
217
|
+
var curOrder2 = parseInt(str(rec2.order) || '0', 10);
|
|
211
218
|
if (uuid2 && curOrder2 >= targetOrder) {
|
|
212
219
|
actionUpdates.push({ order: String(curOrder2 + 1), uiUniqueIdentifier: uuid2, type: 'action' });
|
|
213
220
|
}
|
|
@@ -224,8 +231,8 @@ async function findElementsToReorder(
|
|
|
224
231
|
}
|
|
225
232
|
});
|
|
226
233
|
for (var rec3 of (resp3.data.result || [])) {
|
|
227
|
-
var uuid3 = rec3.ui_unique_identifier;
|
|
228
|
-
var curOrder3 = parseInt(rec3.order || '0', 10);
|
|
234
|
+
var uuid3 = str(rec3.ui_unique_identifier);
|
|
235
|
+
var curOrder3 = parseInt(str(rec3.order) || '0', 10);
|
|
229
236
|
if (uuid3 && curOrder3 >= targetOrder) {
|
|
230
237
|
subflowUpdates.push({ order: String(curOrder3 + 1), uiUniqueIdentifier: uuid3, type: 'subflow' });
|
|
231
238
|
}
|
|
@@ -247,62 +254,78 @@ async function calculateInsertOrder(
|
|
|
247
254
|
): Promise<{ insertOrder: number; reorders: { flowLogicUpdates: any[]; actionUpdates: any[]; subflowUpdates: any[] } }> {
|
|
248
255
|
var noReorders = { flowLogicUpdates: [], actionUpdates: [], subflowUpdates: [] };
|
|
249
256
|
|
|
250
|
-
//
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
var nextOrder = await getNextOrder(client, flowId);
|
|
259
|
-
return { insertOrder: nextOrder, reorders: noReorders };
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
// Parent specified: find parent's order, then find max child order
|
|
263
|
-
var parentSysId = '';
|
|
264
|
-
var parentOrder = 0;
|
|
265
|
-
try {
|
|
266
|
-
var pResp = await client.get('/api/now/table/sys_hub_flow_logic', {
|
|
267
|
-
params: {
|
|
268
|
-
sysparm_query: 'flow=' + flowId + '^ui_unique_identifier=' + parentUiId,
|
|
269
|
-
sysparm_fields: 'sys_id,order',
|
|
270
|
-
sysparm_limit: 1
|
|
271
|
-
}
|
|
272
|
-
});
|
|
273
|
-
var found = pResp.data.result?.[0];
|
|
274
|
-
if (found) {
|
|
275
|
-
parentSysId = found.sys_id;
|
|
276
|
-
parentOrder = parseInt(found.order || '0', 10);
|
|
277
|
-
}
|
|
278
|
-
} catch (_) {}
|
|
279
|
-
|
|
280
|
-
if (!parentSysId) {
|
|
281
|
-
// Fallback: append at end
|
|
282
|
-
var fallbackOrder = await getNextOrder(client, flowId);
|
|
283
|
-
return { insertOrder: fallbackOrder, reorders: noReorders };
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
// Find max order of existing children of this parent
|
|
287
|
-
var maxChildOrder = parentOrder;
|
|
288
|
-
for (var table of ['sys_hub_action_instance', 'sys_hub_flow_logic', 'sys_hub_sub_flow_instance']) {
|
|
257
|
+
// ── Parent specified: ALWAYS compute global order from parent context ──
|
|
258
|
+
// Flow Designer uses GLOBAL ordering for ALL elements (not per-parent).
|
|
259
|
+
// When a parent is specified, any explicit "order" is ignored because callers
|
|
260
|
+
// typically pass a local/relative order (1, 2, 3) which would conflict with
|
|
261
|
+
// elements already at those global positions.
|
|
262
|
+
if (parentUiId) {
|
|
263
|
+
var parentSysId = '';
|
|
264
|
+
var parentOrder = 0;
|
|
289
265
|
try {
|
|
290
|
-
var
|
|
266
|
+
var pResp = await client.get('/api/now/table/sys_hub_flow_logic', {
|
|
291
267
|
params: {
|
|
292
|
-
sysparm_query: 'flow=' + flowId + '^
|
|
293
|
-
sysparm_fields: 'order',
|
|
268
|
+
sysparm_query: 'flow=' + flowId + '^ui_unique_identifier=' + parentUiId,
|
|
269
|
+
sysparm_fields: 'sys_id,order',
|
|
294
270
|
sysparm_limit: 1
|
|
295
271
|
}
|
|
296
272
|
});
|
|
297
|
-
var
|
|
298
|
-
if (
|
|
273
|
+
var found = pResp.data.result?.[0];
|
|
274
|
+
if (found) {
|
|
275
|
+
parentSysId = str(found.sys_id);
|
|
276
|
+
parentOrder = parseInt(str(found.order) || '0', 10);
|
|
277
|
+
}
|
|
299
278
|
} catch (_) {}
|
|
279
|
+
|
|
280
|
+
if (!parentSysId) {
|
|
281
|
+
// Fallback: append at end
|
|
282
|
+
var fallbackOrder = await getNextOrder(client, flowId);
|
|
283
|
+
return { insertOrder: fallbackOrder, reorders: noReorders };
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// Find max order of existing children of this parent (query by both sys_id and UUID)
|
|
287
|
+
var maxChildOrder = parentOrder;
|
|
288
|
+
for (var table of ['sys_hub_action_instance', 'sys_hub_flow_logic', 'sys_hub_sub_flow_instance']) {
|
|
289
|
+
try {
|
|
290
|
+
var cResp = await client.get('/api/now/table/' + table, {
|
|
291
|
+
params: {
|
|
292
|
+
sysparm_query: 'flow=' + flowId + '^parent=' + parentSysId + '^ORDERBYDESCorder',
|
|
293
|
+
sysparm_fields: 'order',
|
|
294
|
+
sysparm_limit: 1
|
|
295
|
+
}
|
|
296
|
+
});
|
|
297
|
+
var childOrder = parseInt(str(cResp.data.result?.[0]?.order) || '0', 10);
|
|
298
|
+
if (childOrder > maxChildOrder) maxChildOrder = childOrder;
|
|
299
|
+
} catch (_) {}
|
|
300
|
+
// Also try querying by parent UUID (GraphQL may store UUID in parent field)
|
|
301
|
+
try {
|
|
302
|
+
var cResp2 = await client.get('/api/now/table/' + table, {
|
|
303
|
+
params: {
|
|
304
|
+
sysparm_query: 'flow=' + flowId + '^parent=' + parentUiId + '^ORDERBYDESCorder',
|
|
305
|
+
sysparm_fields: 'order',
|
|
306
|
+
sysparm_limit: 1
|
|
307
|
+
}
|
|
308
|
+
});
|
|
309
|
+
var childOrder2 = parseInt(str(cResp2.data.result?.[0]?.order) || '0', 10);
|
|
310
|
+
if (childOrder2 > maxChildOrder) maxChildOrder = childOrder2;
|
|
311
|
+
} catch (_) {}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// Insert after last child; bump everything at that position
|
|
315
|
+
var insertOrder = maxChildOrder + 1;
|
|
316
|
+
var reorderInfo = await findElementsToReorder(client, flowId, insertOrder);
|
|
317
|
+
return { insertOrder: insertOrder, reorders: reorderInfo };
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// ── Top-level with explicit order: bump elements at that position ──
|
|
321
|
+
if (explicitOrder) {
|
|
322
|
+
var reorders = await findElementsToReorder(client, flowId, explicitOrder);
|
|
323
|
+
return { insertOrder: explicitOrder, reorders };
|
|
300
324
|
}
|
|
301
325
|
|
|
302
|
-
//
|
|
303
|
-
var
|
|
304
|
-
|
|
305
|
-
return { insertOrder: insertOrder, reorders: reorderInfo };
|
|
326
|
+
// ── Top-level without order: append at end ──
|
|
327
|
+
var nextOrder = await getNextOrder(client, flowId);
|
|
328
|
+
return { insertOrder: nextOrder, reorders: noReorders };
|
|
306
329
|
}
|
|
307
330
|
|
|
308
331
|
async function addTriggerViaGraphQL(
|
|
@@ -326,9 +349,6 @@ async function addTriggerViaGraphQL(
|
|
|
326
349
|
else if (triggerType.endsWith('e')) variations.push(triggerType + 'd');
|
|
327
350
|
else variations.push(triggerType + 'ed', triggerType + 'd');
|
|
328
351
|
|
|
329
|
-
// Resolve reference fields that may be objects {display_value, link} or plain strings
|
|
330
|
-
const str = (val: any) => typeof val === 'object' && val !== null ? (val.display_value || val.value || '') : (val || '');
|
|
331
|
-
|
|
332
352
|
const assignFound = (found: any, matched: string) => {
|
|
333
353
|
trigDefId = found.sys_id;
|
|
334
354
|
trigName = str(found.name) || triggerType;
|
|
@@ -625,7 +645,7 @@ async function addFlowLogicViaGraphQL(
|
|
|
625
645
|
insert: [{
|
|
626
646
|
order: String(resolvedOrder),
|
|
627
647
|
uiUniqueIdentifier: uuid,
|
|
628
|
-
parent: '',
|
|
648
|
+
parent: parentUiId || '',
|
|
629
649
|
metadata: '{"predicates":[]}',
|
|
630
650
|
flowSysId: flowId,
|
|
631
651
|
generationSource: '',
|
|
@@ -637,10 +657,18 @@ async function addFlowLogicViaGraphQL(
|
|
|
637
657
|
}
|
|
638
658
|
};
|
|
639
659
|
|
|
640
|
-
// Merge reorder updates into flowLogics.update
|
|
641
|
-
|
|
660
|
+
// Merge reorder updates + parent update into flowLogics.update
|
|
661
|
+
var flowLogicUpdatesForPatch: any[] = orderCalc.reorders.flowLogicUpdates.slice();
|
|
662
|
+
if (parentUiId) {
|
|
663
|
+
// Signal the parent flow logic was modified (same as action insert does)
|
|
664
|
+
var parentAlreadyInList = flowLogicUpdatesForPatch.some(function (u: any) { return u.uiUniqueIdentifier === parentUiId; });
|
|
665
|
+
if (!parentAlreadyInList) {
|
|
666
|
+
flowLogicUpdatesForPatch.push({ uiUniqueIdentifier: parentUiId, type: 'flowlogic' });
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
if (flowLogicUpdatesForPatch.length > 0) {
|
|
642
670
|
if (!flowPatch.flowLogics.update) flowPatch.flowLogics.update = [];
|
|
643
|
-
flowPatch.flowLogics.update = flowPatch.flowLogics.update.concat(
|
|
671
|
+
flowPatch.flowLogics.update = flowPatch.flowLogics.update.concat(flowLogicUpdatesForPatch);
|
|
644
672
|
}
|
|
645
673
|
if (orderCalc.reorders.actionUpdates.length > 0) {
|
|
646
674
|
flowPatch.actions = { update: orderCalc.reorders.actionUpdates };
|