snow-flow 8.41.16 → 8.41.18
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/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +0 -26
- package/dist/cli.js.map +1 -1
- package/dist/mcp/servicenow-mcp-unified/tools/data-policies/snow_create_data_policy.d.ts +2 -2
- package/dist/mcp/servicenow-mcp-unified/tools/data-policies/snow_create_data_policy.d.ts.map +1 -1
- package/dist/mcp/servicenow-mcp-unified/tools/data-policies/snow_create_data_policy.js +5 -4
- package/dist/mcp/servicenow-mcp-unified/tools/data-policies/snow_create_data_policy.js.map +1 -1
- package/dist/mcp/servicenow-mcp-unified/tools/email/snow_create_notification.d.ts +2 -2
- package/dist/mcp/servicenow-mcp-unified/tools/email/snow_create_notification.d.ts.map +1 -1
- package/dist/mcp/servicenow-mcp-unified/tools/email/snow_create_notification.js +4 -3
- package/dist/mcp/servicenow-mcp-unified/tools/email/snow_create_notification.js.map +1 -1
- package/dist/mcp/servicenow-mcp-unified/tools/flow-designer/index.d.ts +4 -7
- package/dist/mcp/servicenow-mcp-unified/tools/flow-designer/index.d.ts.map +1 -1
- package/dist/mcp/servicenow-mcp-unified/tools/flow-designer/index.js +18 -18
- package/dist/mcp/servicenow-mcp-unified/tools/flow-designer/index.js.map +1 -1
- package/dist/mcp/servicenow-mcp-unified/tools/flow-designer/snow_manage_flow.d.ts +21 -3
- package/dist/mcp/servicenow-mcp-unified/tools/flow-designer/snow_manage_flow.d.ts.map +1 -1
- package/dist/mcp/servicenow-mcp-unified/tools/flow-designer/snow_manage_flow.js +83 -249
- package/dist/mcp/servicenow-mcp-unified/tools/flow-designer/snow_manage_flow.js.map +1 -1
- package/dist/mcp/servicenow-mcp-unified/tools/integration/snow_create_rest_message.d.ts +2 -2
- package/dist/mcp/servicenow-mcp-unified/tools/integration/snow_create_rest_message.d.ts.map +1 -1
- package/dist/mcp/servicenow-mcp-unified/tools/integration/snow_create_rest_message.js +4 -3
- package/dist/mcp/servicenow-mcp-unified/tools/integration/snow_create_rest_message.js.map +1 -1
- package/package.json +1 -1
|
@@ -77,11 +77,6 @@ const error_handler_js_1 = require("../../shared/error-handler.js");
|
|
|
77
77
|
const crypto = __importStar(require("crypto"));
|
|
78
78
|
const zlib = __importStar(require("zlib"));
|
|
79
79
|
// ==================== CONSTANTS ====================
|
|
80
|
-
/**
|
|
81
|
-
* Compression header used by ServiceNow for V2 values fields
|
|
82
|
-
* Note: ServiceNow may not use a header - values are just gzip + base64
|
|
83
|
-
* We detect on read and write without header for compatibility
|
|
84
|
-
*/
|
|
85
80
|
const COMPRESSED_HEADER = 'COMPRESSED:';
|
|
86
81
|
/**
|
|
87
82
|
* Flow Designer Table Structure
|
|
@@ -192,7 +187,31 @@ Features:
|
|
|
192
187
|
},
|
|
193
188
|
trigger: {
|
|
194
189
|
type: 'object',
|
|
195
|
-
description:
|
|
190
|
+
description: `[create] Trigger configuration. Use specific trigger types:
|
|
191
|
+
- record_created: Triggers when a record is created on the specified table
|
|
192
|
+
- record_updated: Triggers when a record is updated
|
|
193
|
+
- record_deleted: Triggers when a record is deleted
|
|
194
|
+
- record_created_or_updated: Triggers on both create and update
|
|
195
|
+
- scheduled: Time-based trigger (requires schedule config)
|
|
196
|
+
- api: REST API trigger
|
|
197
|
+
- inbound_email: Email trigger
|
|
198
|
+
- service_catalog: Catalog item trigger`,
|
|
199
|
+
properties: {
|
|
200
|
+
type: {
|
|
201
|
+
type: 'string',
|
|
202
|
+
enum: ['record_created', 'record_updated', 'record_deleted', 'record_created_or_updated',
|
|
203
|
+
'scheduled', 'api', 'inbound_email', 'service_catalog'],
|
|
204
|
+
description: 'Trigger type - use record_created/record_updated instead of generic record'
|
|
205
|
+
},
|
|
206
|
+
table: {
|
|
207
|
+
type: 'string',
|
|
208
|
+
description: 'Table name for record triggers (e.g., incident, task, sys_user)'
|
|
209
|
+
},
|
|
210
|
+
condition: {
|
|
211
|
+
type: 'string',
|
|
212
|
+
description: 'Filter condition (encoded query) for when the trigger should fire'
|
|
213
|
+
}
|
|
214
|
+
}
|
|
196
215
|
},
|
|
197
216
|
actions: {
|
|
198
217
|
type: 'array',
|
|
@@ -293,20 +312,17 @@ function generateInternalName(name, prefix = 'x_snfl') {
|
|
|
293
312
|
}
|
|
294
313
|
/**
|
|
295
314
|
* Compress value for Xanadu+ versions
|
|
296
|
-
* Uses gzip compression + base64 encoding
|
|
297
|
-
*
|
|
298
|
-
* ServiceNow stores values as: base64(gzip(JSON))
|
|
299
|
-
* No header is used - the data starts directly with base64
|
|
315
|
+
* Uses gzip compression + base64 encoding with COMPRESSED: header
|
|
300
316
|
*/
|
|
301
|
-
function compressValue(value
|
|
317
|
+
function compressValue(value) {
|
|
302
318
|
const jsonStr = typeof value === 'object' ? JSON.stringify(value) : value;
|
|
303
319
|
try {
|
|
304
320
|
// Compress with gzip
|
|
305
321
|
const compressed = zlib.gzipSync(Buffer.from(jsonStr, 'utf-8'));
|
|
306
322
|
// Encode as base64
|
|
307
323
|
const encoded = compressed.toString('base64');
|
|
308
|
-
//
|
|
309
|
-
return
|
|
324
|
+
// Add header
|
|
325
|
+
return COMPRESSED_HEADER + encoded;
|
|
310
326
|
}
|
|
311
327
|
catch (error) {
|
|
312
328
|
console.error('Compression failed, returning uncompressed:', error);
|
|
@@ -315,32 +331,19 @@ function compressValue(value, useHeader = false) {
|
|
|
315
331
|
}
|
|
316
332
|
/**
|
|
317
333
|
* Decompress value from Xanadu+ format
|
|
318
|
-
* Handles both with and without COMPRESSED: header
|
|
319
334
|
*/
|
|
320
335
|
function decompressValue(value) {
|
|
321
|
-
if (!value) {
|
|
336
|
+
if (!value || !value.startsWith(COMPRESSED_HEADER)) {
|
|
322
337
|
return value;
|
|
323
338
|
}
|
|
324
339
|
try {
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
encoded = value.substring(COMPRESSED_HEADER.length);
|
|
329
|
-
}
|
|
330
|
-
// Try to decode base64 and decompress
|
|
340
|
+
// Remove header
|
|
341
|
+
const encoded = value.substring(COMPRESSED_HEADER.length);
|
|
342
|
+
// Decode base64
|
|
331
343
|
const compressed = Buffer.from(encoded, 'base64');
|
|
332
|
-
//
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
return decompressed.toString('utf-8');
|
|
336
|
-
}
|
|
337
|
-
// Not compressed, return original or try as plain base64
|
|
338
|
-
try {
|
|
339
|
-
return Buffer.from(encoded, 'base64').toString('utf-8');
|
|
340
|
-
}
|
|
341
|
-
catch {
|
|
342
|
-
return value;
|
|
343
|
-
}
|
|
344
|
+
// Decompress gzip
|
|
345
|
+
const decompressed = zlib.gunzipSync(compressed);
|
|
346
|
+
return decompressed.toString('utf-8');
|
|
344
347
|
}
|
|
345
348
|
catch (error) {
|
|
346
349
|
console.error('Decompression failed:', error);
|
|
@@ -348,29 +351,9 @@ function decompressValue(value) {
|
|
|
348
351
|
}
|
|
349
352
|
}
|
|
350
353
|
/**
|
|
351
|
-
* Check if value is compressed
|
|
354
|
+
* Check if value is compressed
|
|
352
355
|
*/
|
|
353
356
|
function isCompressed(value) {
|
|
354
|
-
if (!value)
|
|
355
|
-
return false;
|
|
356
|
-
// Check for COMPRESSED: header
|
|
357
|
-
if (value.startsWith(COMPRESSED_HEADER)) {
|
|
358
|
-
return true;
|
|
359
|
-
}
|
|
360
|
-
// Check if it looks like base64 encoded gzip data
|
|
361
|
-
try {
|
|
362
|
-
const decoded = Buffer.from(value, 'base64');
|
|
363
|
-
// Gzip magic bytes: 1f 8b
|
|
364
|
-
return decoded.length >= 2 && decoded[0] === 0x1f && decoded[1] === 0x8b;
|
|
365
|
-
}
|
|
366
|
-
catch {
|
|
367
|
-
return false;
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
/**
|
|
371
|
-
* Check if value uses the COMPRESSED: header format
|
|
372
|
-
*/
|
|
373
|
-
function usesCompressionHeader(value) {
|
|
374
357
|
return value && value.startsWith(COMPRESSED_HEADER);
|
|
375
358
|
}
|
|
376
359
|
/**
|
|
@@ -384,18 +367,15 @@ async function detectVersion(client) {
|
|
|
384
367
|
});
|
|
385
368
|
// Check if values are compressed by looking at a sample
|
|
386
369
|
let useCompression = false;
|
|
387
|
-
let useCompressionHeader = false;
|
|
388
370
|
if (v2Response.data.result && v2Response.data.result.length > 0) {
|
|
389
371
|
const sample = v2Response.data.result[0];
|
|
390
|
-
if (sample.values) {
|
|
391
|
-
useCompression =
|
|
392
|
-
useCompressionHeader = usesCompressionHeader(sample.values);
|
|
372
|
+
if (sample.values && isCompressed(sample.values)) {
|
|
373
|
+
useCompression = true;
|
|
393
374
|
}
|
|
394
375
|
}
|
|
395
376
|
return {
|
|
396
377
|
useV2Tables: true,
|
|
397
378
|
useCompression,
|
|
398
|
-
useCompressionHeader,
|
|
399
379
|
version: useCompression ? 'Xanadu+' : 'Washington DC+'
|
|
400
380
|
};
|
|
401
381
|
}
|
|
@@ -404,7 +384,6 @@ async function detectVersion(client) {
|
|
|
404
384
|
return {
|
|
405
385
|
useV2Tables: false,
|
|
406
386
|
useCompression: false,
|
|
407
|
-
useCompressionHeader: false,
|
|
408
387
|
version: 'Pre-Washington DC'
|
|
409
388
|
};
|
|
410
389
|
}
|
|
@@ -475,10 +454,10 @@ function buildGlideListValue(values) {
|
|
|
475
454
|
* Build values JSON for action instance - ENHANCED VERSION
|
|
476
455
|
* Supports: data pills, references, arrays, scripts, conditions, transforms
|
|
477
456
|
*/
|
|
478
|
-
function buildActionValues(inputs, useCompression
|
|
457
|
+
function buildActionValues(inputs, useCompression) {
|
|
479
458
|
if (!inputs || Object.keys(inputs).length === 0) {
|
|
480
459
|
const emptyValue = '{}';
|
|
481
|
-
return useCompression ? compressValue(emptyValue
|
|
460
|
+
return useCompression ? compressValue(emptyValue) : emptyValue;
|
|
482
461
|
}
|
|
483
462
|
const values = {};
|
|
484
463
|
for (const [key, value] of Object.entries(inputs)) {
|
|
@@ -628,7 +607,7 @@ function buildActionValues(inputs, useCompression, useCompressionHeader = false)
|
|
|
628
607
|
};
|
|
629
608
|
}
|
|
630
609
|
const jsonStr = JSON.stringify(values);
|
|
631
|
-
return useCompression ? compressValue(jsonStr
|
|
610
|
+
return useCompression ? compressValue(jsonStr) : jsonStr;
|
|
632
611
|
}
|
|
633
612
|
/**
|
|
634
613
|
* Remap sys_ids in values JSON when cloning
|
|
@@ -700,12 +679,11 @@ async function getTriggerTypeSysId(client, triggerType, when) {
|
|
|
700
679
|
searchName = triggerMap[triggerType];
|
|
701
680
|
}
|
|
702
681
|
try {
|
|
703
|
-
// Note: sys_hub_trigger_type doesn't have 'label' or 'active' fields
|
|
704
682
|
const response = await client.get('/api/now/table/sys_hub_trigger_type', {
|
|
705
683
|
params: {
|
|
706
|
-
sysparm_query: `nameLIKE${searchName}`,
|
|
684
|
+
sysparm_query: `nameLIKE${searchName}^ORlabelLIKE${searchName}`,
|
|
707
685
|
sysparm_limit: 1,
|
|
708
|
-
sysparm_fields: 'sys_id,name,
|
|
686
|
+
sysparm_fields: 'sys_id,name,label'
|
|
709
687
|
}
|
|
710
688
|
});
|
|
711
689
|
if (response.data.result && response.data.result.length > 0) {
|
|
@@ -725,17 +703,16 @@ async function getActionTypeSysId(client, actionType) {
|
|
|
725
703
|
return { sys_id: actionType, name: actionType };
|
|
726
704
|
}
|
|
727
705
|
try {
|
|
728
|
-
// Note: sys_hub_action_type_base doesn't have 'label' or 'active' fields
|
|
729
706
|
const response = await client.get('/api/now/table/sys_hub_action_type_base', {
|
|
730
707
|
params: {
|
|
731
|
-
sysparm_query: `nameLIKE${actionType}`,
|
|
708
|
+
sysparm_query: `nameLIKE${actionType}^ORlabelLIKE${actionType}^active=true`,
|
|
732
709
|
sysparm_limit: 1,
|
|
733
|
-
sysparm_fields: 'sys_id,name,
|
|
710
|
+
sysparm_fields: 'sys_id,name,label'
|
|
734
711
|
}
|
|
735
712
|
});
|
|
736
713
|
if (response.data.result && response.data.result.length > 0) {
|
|
737
714
|
const result = response.data.result[0];
|
|
738
|
-
return { sys_id: result.sys_id, name: result.name };
|
|
715
|
+
return { sys_id: result.sys_id, name: result.name || result.label };
|
|
739
716
|
}
|
|
740
717
|
}
|
|
741
718
|
catch (error) {
|
|
@@ -874,7 +851,13 @@ async function handleCreate(args, client, versionInfo) {
|
|
|
874
851
|
active: true,
|
|
875
852
|
order: 0
|
|
876
853
|
};
|
|
877
|
-
|
|
854
|
+
// Handle record triggers (both legacy 'record' type and new specific types)
|
|
855
|
+
const isRecordTrigger = triggerConfig.type === 'record' ||
|
|
856
|
+
triggerConfig.type === 'record_created' ||
|
|
857
|
+
triggerConfig.type === 'record_updated' ||
|
|
858
|
+
triggerConfig.type === 'record_deleted' ||
|
|
859
|
+
triggerConfig.type === 'record_created_or_updated';
|
|
860
|
+
if (isRecordTrigger) {
|
|
878
861
|
if (triggerConfig.table)
|
|
879
862
|
triggerData.table = triggerConfig.table;
|
|
880
863
|
if (triggerConfig.condition) {
|
|
@@ -912,10 +895,9 @@ async function handleCreate(args, client, versionInfo) {
|
|
|
912
895
|
'reference': 'reference', 'object': 'object', 'array': 'array',
|
|
913
896
|
'glide_date_time': 'glide_date_time'
|
|
914
897
|
};
|
|
915
|
-
// Note: sys_hub_flow_variable uses 'model' field (not 'flow') to reference the parent flow
|
|
916
898
|
const variableData = {
|
|
917
899
|
sys_id: variableSysId,
|
|
918
|
-
|
|
900
|
+
flow: flowSysId,
|
|
919
901
|
name: variable.name,
|
|
920
902
|
label: variable.label || variable.name,
|
|
921
903
|
description: variable.description || '',
|
|
@@ -983,7 +965,7 @@ async function handleCreate(args, client, versionInfo) {
|
|
|
983
965
|
branch: 'then'
|
|
984
966
|
};
|
|
985
967
|
if (thenAction.inputs) {
|
|
986
|
-
actionData.values = buildActionValues(thenAction.inputs, useCompression
|
|
968
|
+
actionData.values = buildActionValues(thenAction.inputs, useCompression);
|
|
987
969
|
}
|
|
988
970
|
try {
|
|
989
971
|
await client.post(`/api/now/table/${actionTable}`, actionData);
|
|
@@ -1022,7 +1004,7 @@ async function handleCreate(args, client, versionInfo) {
|
|
|
1022
1004
|
branch: 'else'
|
|
1023
1005
|
};
|
|
1024
1006
|
if (elseAction.inputs) {
|
|
1025
|
-
actionData.values = buildActionValues(elseAction.inputs, useCompression
|
|
1007
|
+
actionData.values = buildActionValues(elseAction.inputs, useCompression);
|
|
1026
1008
|
}
|
|
1027
1009
|
try {
|
|
1028
1010
|
await client.post(`/api/now/table/${actionTable}`, actionData);
|
|
@@ -1096,7 +1078,7 @@ async function handleCreate(args, client, versionInfo) {
|
|
|
1096
1078
|
parent_logic_instance: loopSysId
|
|
1097
1079
|
};
|
|
1098
1080
|
if (loopAction.inputs) {
|
|
1099
|
-
actionData.values = buildActionValues(loopAction.inputs, useCompression
|
|
1081
|
+
actionData.values = buildActionValues(loopAction.inputs, useCompression);
|
|
1100
1082
|
}
|
|
1101
1083
|
try {
|
|
1102
1084
|
await client.post(`/api/now/table/${actionTable}`, actionData);
|
|
@@ -1144,7 +1126,7 @@ async function handleCreate(args, client, versionInfo) {
|
|
|
1144
1126
|
active: true
|
|
1145
1127
|
};
|
|
1146
1128
|
if (actionConfig.inputs) {
|
|
1147
|
-
actionData.values = buildActionValues(actionConfig.inputs, useCompression
|
|
1129
|
+
actionData.values = buildActionValues(actionConfig.inputs, useCompression);
|
|
1148
1130
|
}
|
|
1149
1131
|
try {
|
|
1150
1132
|
await client.post(`/api/now/table/${actionTable}`, actionData);
|
|
@@ -1156,65 +1138,21 @@ async function handleCreate(args, client, versionInfo) {
|
|
|
1156
1138
|
}
|
|
1157
1139
|
currentOrder += 100;
|
|
1158
1140
|
}
|
|
1159
|
-
// 7. CREATE SNAPSHOT
|
|
1160
|
-
// This is CRITICAL - Flow Designer requires snapshots with main_snapshot/latest_snapshot references
|
|
1141
|
+
// 7. CREATE SNAPSHOT
|
|
1161
1142
|
if (create_snapshot) {
|
|
1162
|
-
console.log('Creating snapshot
|
|
1163
|
-
// Build the flow definition structure that Flow Designer expects
|
|
1164
|
-
const flowDefinition = {
|
|
1165
|
-
sys_id: flowSysId,
|
|
1166
|
-
name: flowConfig.name,
|
|
1167
|
-
internal_name: internalName,
|
|
1168
|
-
description: flowConfig.description || '',
|
|
1169
|
-
flow_type: 'flow',
|
|
1170
|
-
run_as: flowConfig.run_as || 'system',
|
|
1171
|
-
// Include references to created components
|
|
1172
|
-
trigger: triggerConfig ? {
|
|
1173
|
-
sys_id: triggerSysId,
|
|
1174
|
-
type: triggerConfig.type,
|
|
1175
|
-
table: triggerConfig.table,
|
|
1176
|
-
when: triggerConfig.when
|
|
1177
|
-
} : null,
|
|
1178
|
-
actions: createdRecords
|
|
1179
|
-
.filter(r => r.table === actionTable)
|
|
1180
|
-
.map(r => ({ sys_id: r.sys_id, name: r.name })),
|
|
1181
|
-
logic: createdRecords
|
|
1182
|
-
.filter(r => r.table === logicTable)
|
|
1183
|
-
.map(r => ({ sys_id: r.sys_id, name: r.name, type: r.type })),
|
|
1184
|
-
variables: createdRecords
|
|
1185
|
-
.filter(r => r.table === FLOW_TABLES.VARIABLE)
|
|
1186
|
-
.map(r => ({ sys_id: r.sys_id, name: r.name }))
|
|
1187
|
-
};
|
|
1143
|
+
console.log('Creating snapshot...');
|
|
1188
1144
|
const snapshotData = {
|
|
1189
1145
|
sys_id: snapshotSysId,
|
|
1190
1146
|
flow: flowSysId,
|
|
1191
1147
|
name: `${flowConfig.name} - Initial`,
|
|
1192
1148
|
version: '1.0.0',
|
|
1193
1149
|
active: true,
|
|
1194
|
-
published: false
|
|
1195
|
-
// Store the flow definition - this is what Flow Designer reads
|
|
1196
|
-
definition: useCompression
|
|
1197
|
-
? compressValue(flowDefinition, versionInfo.useCompressionHeader)
|
|
1198
|
-
: JSON.stringify(flowDefinition)
|
|
1150
|
+
published: false
|
|
1199
1151
|
};
|
|
1200
1152
|
try {
|
|
1201
1153
|
await client.post(`/api/now/table/${FLOW_TABLES.SNAPSHOT}`, snapshotData);
|
|
1202
1154
|
createdRecords.push({ table: FLOW_TABLES.SNAPSHOT, sys_id: snapshotSysId, name: `${flowConfig.name} - Initial` });
|
|
1203
1155
|
console.log(`✅ Created snapshot: ${snapshotSysId}`);
|
|
1204
|
-
// *** CRITICAL FIX ***
|
|
1205
|
-
// Update the flow record with snapshot references
|
|
1206
|
-
// Without this, Flow Designer shows an empty flow!
|
|
1207
|
-
console.log('Updating flow with snapshot references...');
|
|
1208
|
-
try {
|
|
1209
|
-
await client.patch(`/api/now/table/${FLOW_TABLES.FLOW}/${flowSysId}`, {
|
|
1210
|
-
main_snapshot: snapshotSysId,
|
|
1211
|
-
latest_snapshot: snapshotSysId
|
|
1212
|
-
});
|
|
1213
|
-
console.log(`✅ Flow updated with main_snapshot and latest_snapshot`);
|
|
1214
|
-
}
|
|
1215
|
-
catch (updateError) {
|
|
1216
|
-
errors.push(`Failed to update flow with snapshot references: ${updateError.response?.data?.error?.message || updateError.message}`);
|
|
1217
|
-
}
|
|
1218
1156
|
}
|
|
1219
1157
|
catch (error) {
|
|
1220
1158
|
errors.push(`Failed to create snapshot: ${error.response?.data?.error?.message || error.message}`);
|
|
@@ -1243,9 +1181,7 @@ async function handleCreate(args, client, versionInfo) {
|
|
|
1243
1181
|
internal_name: internalName,
|
|
1244
1182
|
active: auto_activate && errors.length === 0,
|
|
1245
1183
|
url: `${instanceUrl}/sys_hub_flow.do?sys_id=${flowSysId}`,
|
|
1246
|
-
flow_designer_url: `${instanceUrl}/nav_to.do?uri
|
|
1247
|
-
main_snapshot: create_snapshot ? snapshotSysId : undefined,
|
|
1248
|
-
latest_snapshot: create_snapshot ? snapshotSysId : undefined
|
|
1184
|
+
flow_designer_url: `${instanceUrl}/nav_to.do?uri=/$flow-designer.do#/flow/${flowSysId}`
|
|
1249
1185
|
},
|
|
1250
1186
|
created_records: createdRecords,
|
|
1251
1187
|
version_info: versionInfo,
|
|
@@ -1386,9 +1322,8 @@ async function handleDelete(args, client, versionInfo) {
|
|
|
1386
1322
|
console.log('Deleting triggers...');
|
|
1387
1323
|
await deleteFromTable(triggerTable, `flow=${flow.sys_id}`);
|
|
1388
1324
|
// 5. DELETE VARIABLES
|
|
1389
|
-
// Note: sys_hub_flow_variable uses 'model' field (not 'flow')
|
|
1390
1325
|
console.log('Deleting variables...');
|
|
1391
|
-
await deleteFromTable(FLOW_TABLES.VARIABLE, `
|
|
1326
|
+
await deleteFromTable(FLOW_TABLES.VARIABLE, `flow=${flow.sys_id}`);
|
|
1392
1327
|
// 6. DELETE SNAPSHOTS
|
|
1393
1328
|
console.log('Deleting snapshots...');
|
|
1394
1329
|
await deleteFromTable(FLOW_TABLES.SNAPSHOT, `flow=${flow.sys_id}`);
|
|
@@ -1476,19 +1411,17 @@ async function handleClone(args, client, versionInfo) {
|
|
|
1476
1411
|
return (0, error_handler_js_1.createErrorResult)(`Failed to create cloned flow: ${error.response?.data?.error?.message || error.message}`);
|
|
1477
1412
|
}
|
|
1478
1413
|
// ==================== 2. CLONE VARIABLES ====================
|
|
1479
|
-
// Note: sys_hub_flow_variable uses 'model' field (not 'flow')
|
|
1480
1414
|
try {
|
|
1481
1415
|
const variablesResponse = await client.get(`/api/now/table/${FLOW_TABLES.VARIABLE}`, {
|
|
1482
|
-
params: { sysparm_query: `
|
|
1416
|
+
params: { sysparm_query: `flow=${sourceFlow.sys_id}`, sysparm_orderby: 'order' }
|
|
1483
1417
|
});
|
|
1484
1418
|
if (variablesResponse.data.result) {
|
|
1485
1419
|
for (const variable of variablesResponse.data.result) {
|
|
1486
1420
|
const newVariableId = generateSysId();
|
|
1487
1421
|
sysIdMap.set(variable.sys_id, newVariableId);
|
|
1488
|
-
// Note: sys_hub_flow_variable uses 'model' field (not 'flow')
|
|
1489
1422
|
const newVariable = {
|
|
1490
1423
|
sys_id: newVariableId,
|
|
1491
|
-
|
|
1424
|
+
flow: newFlowId,
|
|
1492
1425
|
name: variable.name,
|
|
1493
1426
|
label: variable.label,
|
|
1494
1427
|
description: variable.description,
|
|
@@ -1775,57 +1708,25 @@ async function handleClone(args, client, versionInfo) {
|
|
|
1775
1708
|
// Subflow table might not exist or be empty
|
|
1776
1709
|
}
|
|
1777
1710
|
// ==================== 7. CREATE SNAPSHOT ====================
|
|
1778
|
-
let clonedSnapshotId;
|
|
1779
1711
|
if (create_snapshot) {
|
|
1780
|
-
|
|
1781
|
-
// Build flow definition for snapshot
|
|
1782
|
-
const flowDefinition = {
|
|
1783
|
-
sys_id: newFlowId,
|
|
1784
|
-
name: new_name,
|
|
1785
|
-
internal_name: newInternalName,
|
|
1786
|
-
cloned_from: sourceFlow.sys_id,
|
|
1787
|
-
// Include created components
|
|
1788
|
-
components: createdRecords.map(r => ({
|
|
1789
|
-
table: r.table,
|
|
1790
|
-
sys_id: r.sys_id,
|
|
1791
|
-
name: r.name,
|
|
1792
|
-
type: r.type
|
|
1793
|
-
}))
|
|
1794
|
-
};
|
|
1712
|
+
const snapshotId = generateSysId();
|
|
1795
1713
|
const snapshotData = {
|
|
1796
|
-
sys_id:
|
|
1714
|
+
sys_id: snapshotId,
|
|
1797
1715
|
flow: newFlowId,
|
|
1798
1716
|
name: `${new_name} - Initial (Cloned)`,
|
|
1799
1717
|
version: '1.0.0',
|
|
1800
1718
|
active: true,
|
|
1801
|
-
published: false
|
|
1802
|
-
// Include flow definition
|
|
1803
|
-
definition: useCompression
|
|
1804
|
-
? compressValue(flowDefinition, versionInfo.useCompressionHeader)
|
|
1805
|
-
: JSON.stringify(flowDefinition)
|
|
1719
|
+
published: false
|
|
1806
1720
|
};
|
|
1807
1721
|
try {
|
|
1808
1722
|
await client.post(`/api/now/table/${FLOW_TABLES.SNAPSHOT}`, snapshotData);
|
|
1809
1723
|
createdRecords.push({
|
|
1810
1724
|
table: FLOW_TABLES.SNAPSHOT,
|
|
1811
|
-
sys_id:
|
|
1725
|
+
sys_id: snapshotId,
|
|
1812
1726
|
name: snapshotData.name,
|
|
1813
1727
|
type: 'snapshot'
|
|
1814
1728
|
});
|
|
1815
|
-
console.log(`✅ Created snapshot: ${
|
|
1816
|
-
// *** CRITICAL FIX ***
|
|
1817
|
-
// Update the cloned flow with snapshot references
|
|
1818
|
-
console.log('Updating cloned flow with snapshot references...');
|
|
1819
|
-
try {
|
|
1820
|
-
await client.patch(`/api/now/table/${FLOW_TABLES.FLOW}/${newFlowId}`, {
|
|
1821
|
-
main_snapshot: clonedSnapshotId,
|
|
1822
|
-
latest_snapshot: clonedSnapshotId
|
|
1823
|
-
});
|
|
1824
|
-
console.log(`✅ Cloned flow updated with main_snapshot and latest_snapshot`);
|
|
1825
|
-
}
|
|
1826
|
-
catch (updateError) {
|
|
1827
|
-
errors.push(`Failed to update cloned flow with snapshot references: ${updateError.message}`);
|
|
1828
|
-
}
|
|
1729
|
+
console.log(`✅ Created snapshot: ${snapshotId}`);
|
|
1829
1730
|
}
|
|
1830
1731
|
catch (e) {
|
|
1831
1732
|
errors.push(`Failed to create snapshot: ${e.message}`);
|
|
@@ -1856,9 +1757,7 @@ async function handleClone(args, client, versionInfo) {
|
|
|
1856
1757
|
internal_name: newInternalName,
|
|
1857
1758
|
active: false,
|
|
1858
1759
|
url: `${instanceUrl}/sys_hub_flow.do?sys_id=${newFlowId}`,
|
|
1859
|
-
flow_designer_url: `${instanceUrl}/nav_to.do?uri
|
|
1860
|
-
main_snapshot: clonedSnapshotId,
|
|
1861
|
-
latest_snapshot: clonedSnapshotId
|
|
1760
|
+
flow_designer_url: `${instanceUrl}/nav_to.do?uri=/$flow-designer.do#/flow/${newFlowId}`
|
|
1862
1761
|
},
|
|
1863
1762
|
summary,
|
|
1864
1763
|
created_records: createdRecords,
|
|
@@ -1953,7 +1852,7 @@ async function handleAddAction(args, client, versionInfo) {
|
|
|
1953
1852
|
actionData.branch = action_config.branch;
|
|
1954
1853
|
}
|
|
1955
1854
|
if (action_config.inputs) {
|
|
1956
|
-
actionData.values = buildActionValues(action_config.inputs, useCompression
|
|
1855
|
+
actionData.values = buildActionValues(action_config.inputs, useCompression);
|
|
1957
1856
|
}
|
|
1958
1857
|
try {
|
|
1959
1858
|
await client.post(`/api/now/table/${actionTable}`, actionData);
|
|
@@ -2106,12 +2005,11 @@ async function handleAddVariable(args, client) {
|
|
|
2106
2005
|
}
|
|
2107
2006
|
const variableSysId = generateSysId();
|
|
2108
2007
|
// Get max order for variables
|
|
2109
|
-
// Note: sys_hub_flow_variable uses 'model' field (not 'flow')
|
|
2110
2008
|
let maxOrder = 0;
|
|
2111
2009
|
try {
|
|
2112
2010
|
const response = await client.get(`/api/now/table/${FLOW_TABLES.VARIABLE}`, {
|
|
2113
2011
|
params: {
|
|
2114
|
-
sysparm_query: `
|
|
2012
|
+
sysparm_query: `flow=${flow.sys_id}`,
|
|
2115
2013
|
sysparm_fields: 'order',
|
|
2116
2014
|
sysparm_orderby: 'DESCorder',
|
|
2117
2015
|
sysparm_limit: 1
|
|
@@ -2124,7 +2022,7 @@ async function handleAddVariable(args, client) {
|
|
|
2124
2022
|
catch (e) { }
|
|
2125
2023
|
const variableData = {
|
|
2126
2024
|
sys_id: variableSysId,
|
|
2127
|
-
|
|
2025
|
+
flow: flow.sys_id,
|
|
2128
2026
|
name: variable_config.name,
|
|
2129
2027
|
label: variable_config.label || variable_config.name,
|
|
2130
2028
|
description: variable_config.description || '',
|
|
@@ -2237,10 +2135,9 @@ async function handleGetDetails(args, client, versionInfo) {
|
|
|
2237
2135
|
}
|
|
2238
2136
|
catch (e) { }
|
|
2239
2137
|
// Get variables
|
|
2240
|
-
// Note: sys_hub_flow_variable uses 'model' field (not 'flow')
|
|
2241
2138
|
try {
|
|
2242
2139
|
const response = await client.get(`/api/now/table/${FLOW_TABLES.VARIABLE}`, {
|
|
2243
|
-
params: { sysparm_query: `
|
|
2140
|
+
params: { sysparm_query: `flow=${flow.sys_id}`, sysparm_orderby: 'order' }
|
|
2244
2141
|
});
|
|
2245
2142
|
if (response.data.result) {
|
|
2246
2143
|
details.variables = response.data.result;
|
|
@@ -2312,66 +2209,14 @@ async function handlePublish(args, client, versionInfo) {
|
|
|
2312
2209
|
return (0, error_handler_js_1.createErrorResult)(`Flow not found: ${flow_id || flow_name}`);
|
|
2313
2210
|
}
|
|
2314
2211
|
const snapshotSysId = generateSysId();
|
|
2315
|
-
|
|
2316
|
-
// Get existing flow components for the definition
|
|
2317
|
-
const actionTable = versionInfo.useV2Tables ? FLOW_TABLES.ACTION_V2 : FLOW_TABLES.ACTION_V1;
|
|
2318
|
-
const triggerTable = versionInfo.useV2Tables ? FLOW_TABLES.TRIGGER_V2 : FLOW_TABLES.TRIGGER_V1;
|
|
2319
|
-
const logicTable = versionInfo.useV2Tables ? FLOW_TABLES.LOGIC_V2 : FLOW_TABLES.LOGIC_V1;
|
|
2320
|
-
// Fetch existing components
|
|
2321
|
-
let actions = [];
|
|
2322
|
-
let triggers = [];
|
|
2323
|
-
let logic = [];
|
|
2324
|
-
let variables = [];
|
|
2325
|
-
try {
|
|
2326
|
-
const actionsResp = await client.get(`/api/now/table/${actionTable}`, {
|
|
2327
|
-
params: { sysparm_query: `flow=${flow.sys_id}`, sysparm_fields: 'sys_id,name,order' }
|
|
2328
|
-
});
|
|
2329
|
-
actions = actionsResp.data.result || [];
|
|
2330
|
-
}
|
|
2331
|
-
catch (e) { }
|
|
2332
|
-
try {
|
|
2333
|
-
const triggersResp = await client.get(`/api/now/table/${triggerTable}`, {
|
|
2334
|
-
params: { sysparm_query: `flow=${flow.sys_id}`, sysparm_fields: 'sys_id,trigger_type' }
|
|
2335
|
-
});
|
|
2336
|
-
triggers = triggersResp.data.result || [];
|
|
2337
|
-
}
|
|
2338
|
-
catch (e) { }
|
|
2339
|
-
try {
|
|
2340
|
-
const logicResp = await client.get(`/api/now/table/${logicTable}`, {
|
|
2341
|
-
params: { sysparm_query: `flow=${flow.sys_id}`, sysparm_fields: 'sys_id,name,logic_type' }
|
|
2342
|
-
});
|
|
2343
|
-
logic = logicResp.data.result || [];
|
|
2344
|
-
}
|
|
2345
|
-
catch (e) { }
|
|
2346
|
-
try {
|
|
2347
|
-
const variablesResp = await client.get(`/api/now/table/${FLOW_TABLES.VARIABLE}`, {
|
|
2348
|
-
params: { sysparm_query: `model=${flow.sys_id}`, sysparm_fields: 'sys_id,name,type,direction' }
|
|
2349
|
-
});
|
|
2350
|
-
variables = variablesResp.data.result || [];
|
|
2351
|
-
}
|
|
2352
|
-
catch (e) { }
|
|
2353
|
-
// Build flow definition
|
|
2354
|
-
const flowDefinition = {
|
|
2355
|
-
sys_id: flow.sys_id,
|
|
2356
|
-
name: flow.name,
|
|
2357
|
-
internal_name: flow.internal_name,
|
|
2358
|
-
published_at: new Date().toISOString(),
|
|
2359
|
-
triggers: triggers.map(t => ({ sys_id: t.sys_id, trigger_type: t.trigger_type })),
|
|
2360
|
-
actions: actions.map(a => ({ sys_id: a.sys_id, name: a.name, order: a.order })),
|
|
2361
|
-
logic: logic.map(l => ({ sys_id: l.sys_id, name: l.name, logic_type: l.logic_type })),
|
|
2362
|
-
variables: variables.map(v => ({ sys_id: v.sys_id, name: v.name, type: v.type, direction: v.direction }))
|
|
2363
|
-
};
|
|
2364
|
-
// Create new snapshot with definition
|
|
2212
|
+
// Create new snapshot
|
|
2365
2213
|
const snapshotData = {
|
|
2366
2214
|
sys_id: snapshotSysId,
|
|
2367
2215
|
flow: flow.sys_id,
|
|
2368
2216
|
name: `${flow.name} - Published ${new Date().toISOString()}`,
|
|
2369
2217
|
version: '1.0.0',
|
|
2370
2218
|
active: true,
|
|
2371
|
-
published: true
|
|
2372
|
-
definition: useCompression
|
|
2373
|
-
? compressValue(flowDefinition, versionInfo.useCompressionHeader)
|
|
2374
|
-
: JSON.stringify(flowDefinition)
|
|
2219
|
+
published: true
|
|
2375
2220
|
};
|
|
2376
2221
|
try {
|
|
2377
2222
|
await client.post(`/api/now/table/${FLOW_TABLES.SNAPSHOT}`, snapshotData);
|
|
@@ -2379,14 +2224,11 @@ async function handlePublish(args, client, versionInfo) {
|
|
|
2379
2224
|
catch (error) {
|
|
2380
2225
|
return (0, error_handler_js_1.createErrorResult)(`Failed to create snapshot: ${error.response?.data?.error?.message || error.message}`);
|
|
2381
2226
|
}
|
|
2382
|
-
//
|
|
2383
|
-
// Update flow with snapshot references AND activate
|
|
2227
|
+
// Activate flow
|
|
2384
2228
|
try {
|
|
2385
2229
|
await client.patch(`/api/now/table/${FLOW_TABLES.FLOW}/${flow.sys_id}`, {
|
|
2386
2230
|
active: true,
|
|
2387
|
-
status: 'published'
|
|
2388
|
-
main_snapshot: snapshotSysId,
|
|
2389
|
-
latest_snapshot: snapshotSysId
|
|
2231
|
+
status: 'published'
|
|
2390
2232
|
});
|
|
2391
2233
|
}
|
|
2392
2234
|
catch (error) {
|
|
@@ -2397,15 +2239,7 @@ async function handlePublish(args, client, versionInfo) {
|
|
|
2397
2239
|
flow_id: flow.sys_id,
|
|
2398
2240
|
flow_name: flow.name,
|
|
2399
2241
|
snapshot_id: snapshotSysId,
|
|
2400
|
-
|
|
2401
|
-
latest_snapshot: snapshotSysId,
|
|
2402
|
-
active: true,
|
|
2403
|
-
components_included: {
|
|
2404
|
-
triggers: triggers.length,
|
|
2405
|
-
actions: actions.length,
|
|
2406
|
-
logic: logic.length,
|
|
2407
|
-
variables: variables.length
|
|
2408
|
-
}
|
|
2242
|
+
active: true
|
|
2409
2243
|
});
|
|
2410
2244
|
}
|
|
2411
2245
|
// ==================== MAIN EXECUTOR ====================
|
|
@@ -2454,6 +2288,6 @@ async function execute(args, context) {
|
|
|
2454
2288
|
return (0, error_handler_js_1.createErrorResult)(`Flow management failed: ${error.message}`);
|
|
2455
2289
|
}
|
|
2456
2290
|
}
|
|
2457
|
-
exports.version = '2.1.0';
|
|
2458
|
-
exports.author = 'Snow-Flow v8.41.
|
|
2291
|
+
exports.version = '2.1.0-experimental';
|
|
2292
|
+
exports.author = 'Snow-Flow v8.41.17 - Flow Designer Management';
|
|
2459
2293
|
//# sourceMappingURL=snow_manage_flow.js.map
|