snow-flow-test 10.0.1-test.110 → 10.0.1-test.111
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
|
@@ -47,15 +47,29 @@ var _bootstrapPromise: Promise<{ namespace: string; apiSysId: string }> | null =
|
|
|
47
47
|
*/
|
|
48
48
|
var FLOW_FACTORY_SCRIPT = [
|
|
49
49
|
'(function process(/*RESTAPIRequest*/ request, /*RESTAPIResponse*/ response) {',
|
|
50
|
-
' var body;',
|
|
51
|
-
'
|
|
52
|
-
'
|
|
50
|
+
' var body = null;',
|
|
51
|
+
' var parseLog = [];',
|
|
52
|
+
' try {',
|
|
53
|
+
' var ds = request.body.dataString;',
|
|
54
|
+
' if (ds) { body = JSON.parse(ds + ""); parseLog.push("dataString:ok"); }',
|
|
55
|
+
' } catch(e1) { parseLog.push("dataString:" + e1); }',
|
|
56
|
+
' if (!body) {',
|
|
57
|
+
' try {',
|
|
58
|
+
' var d = request.body.data;',
|
|
59
|
+
' if (d && typeof d === "object") { body = d; parseLog.push("data:ok"); }',
|
|
60
|
+
' else if (d) { body = JSON.parse(d + ""); parseLog.push("data-parse:ok"); }',
|
|
61
|
+
' } catch(e2) { parseLog.push("data:" + e2); }',
|
|
62
|
+
' }',
|
|
63
|
+
' if (!body) {',
|
|
64
|
+
' try { body = JSON.parse(request.body + ""); parseLog.push("body-direct:ok"); }',
|
|
65
|
+
' catch(e3) { parseLog.push("body-direct:" + e3); }',
|
|
66
|
+
' }',
|
|
53
67
|
' if (!body || typeof body !== "object") {',
|
|
54
68
|
' response.setStatus(400);',
|
|
55
|
-
' response.setBody({ success: false, error: "
|
|
69
|
+
' response.setBody({ success: false, error: "No parseable body", parseLog: parseLog, bodyType: typeof request.body });',
|
|
56
70
|
' return;',
|
|
57
71
|
' }',
|
|
58
|
-
' var result = { success: false, steps: {} };',
|
|
72
|
+
' var result = { success: false, steps: {}, parseLog: parseLog };',
|
|
59
73
|
'',
|
|
60
74
|
' try {',
|
|
61
75
|
' var flowName = body.name || "Unnamed Flow";',
|
|
@@ -419,6 +433,88 @@ function invalidateFlowFactoryCache(): void {
|
|
|
419
433
|
_flowFactoryCache = null;
|
|
420
434
|
}
|
|
421
435
|
|
|
436
|
+
/**
|
|
437
|
+
* After creating a flow (via any method), try to register it with the
|
|
438
|
+
* Flow Designer engine by calling its built-in compile / publish / activate
|
|
439
|
+
* REST endpoints. Without this step the flow record exists in the DB but
|
|
440
|
+
* Flow Designer cannot open it ("Your flow cannot be found").
|
|
441
|
+
*
|
|
442
|
+
* Tries multiple known endpoint patterns because the namespace/path changed
|
|
443
|
+
* across ServiceNow releases. Returns diagnostics on which attempts were
|
|
444
|
+
* made and what succeeded.
|
|
445
|
+
*/
|
|
446
|
+
async function registerFlowWithEngine(
|
|
447
|
+
client: any,
|
|
448
|
+
flowSysId: string,
|
|
449
|
+
shouldActivate: boolean
|
|
450
|
+
): Promise<{ success: boolean; method: string; attempts: string[] }> {
|
|
451
|
+
var attempts: string[] = [];
|
|
452
|
+
|
|
453
|
+
// Helper: try a POST and classify the result
|
|
454
|
+
async function tryPost(label: string, url: string, body?: any): Promise<boolean> {
|
|
455
|
+
try {
|
|
456
|
+
await client.post(url, body || {});
|
|
457
|
+
attempts.push(label + ': success');
|
|
458
|
+
return true;
|
|
459
|
+
} catch (e: any) {
|
|
460
|
+
var s = e.response?.status || 'err';
|
|
461
|
+
attempts.push(label + ': ' + s);
|
|
462
|
+
return false;
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
// ── Strategy 1: Publish via Flow Designer REST API ───────────────
|
|
467
|
+
// This is the closest equivalent to clicking "Publish" in the UI.
|
|
468
|
+
var publishPaths = [
|
|
469
|
+
'/api/sn_fd/flow/' + flowSysId + '/publish',
|
|
470
|
+
'/api/sn_fd/designer/flow/' + flowSysId + '/publish',
|
|
471
|
+
'/api/sn_flow_designer/flow/' + flowSysId + '/publish',
|
|
472
|
+
];
|
|
473
|
+
for (var pi = 0; pi < publishPaths.length; pi++) {
|
|
474
|
+
if (await tryPost('publish[' + pi + ']', publishPaths[pi])) {
|
|
475
|
+
return { success: true, method: 'publish', attempts: attempts };
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
// ── Strategy 2: Activate (registers the flow with the engine) ────
|
|
480
|
+
if (shouldActivate) {
|
|
481
|
+
var activatePaths = [
|
|
482
|
+
'/api/sn_fd/flow/' + flowSysId + '/activate',
|
|
483
|
+
'/api/sn_fd/designer/flow/' + flowSysId + '/activate',
|
|
484
|
+
'/api/sn_flow_designer/flow/' + flowSysId + '/activate',
|
|
485
|
+
];
|
|
486
|
+
for (var ai = 0; ai < activatePaths.length; ai++) {
|
|
487
|
+
if (await tryPost('activate[' + ai + ']', activatePaths[ai])) {
|
|
488
|
+
return { success: true, method: 'activate', attempts: attempts };
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
// ── Strategy 3: Checkout + checkin (triggers internal compilation) ─
|
|
494
|
+
var checkoutPaths = [
|
|
495
|
+
'/api/sn_fd/flow/' + flowSysId + '/checkout',
|
|
496
|
+
'/api/sn_fd/designer/flow/' + flowSysId + '/checkout',
|
|
497
|
+
];
|
|
498
|
+
for (var ci = 0; ci < checkoutPaths.length; ci++) {
|
|
499
|
+
if (await tryPost('checkout[' + ci + ']', checkoutPaths[ci])) {
|
|
500
|
+
var checkinPath = checkoutPaths[ci].replace('/checkout', '/checkin');
|
|
501
|
+
await tryPost('checkin[' + ci + ']', checkinPath);
|
|
502
|
+
return { success: true, method: 'checkout+checkin', attempts: attempts };
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
// ── Strategy 4: Snapshot (already existed — triggers version snapshot) ─
|
|
507
|
+
if (await tryPost('snapshot', '/api/sn_flow_designer/flow/snapshot', { flow_id: flowSysId })) {
|
|
508
|
+
return { success: true, method: 'snapshot', attempts: attempts };
|
|
509
|
+
}
|
|
510
|
+
// Try alternate snapshot path
|
|
511
|
+
if (await tryPost('snapshot-alt', '/api/sn_fd/flow/' + flowSysId + '/snapshot')) {
|
|
512
|
+
return { success: true, method: 'snapshot-alt', attempts: attempts };
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
return { success: false, method: 'none', attempts: attempts };
|
|
516
|
+
}
|
|
517
|
+
|
|
422
518
|
/**
|
|
423
519
|
* Resolve a flow name to its sys_id. If the value is already a 32-char hex
|
|
424
520
|
* string it is returned as-is.
|
|
@@ -675,7 +771,7 @@ export async function execute(args: any, context: ServiceNowContext): Promise<To
|
|
|
675
771
|
version_created: false,
|
|
676
772
|
version_method: null,
|
|
677
773
|
version_fields_set: [] as string[],
|
|
678
|
-
|
|
774
|
+
engine_registration: null,
|
|
679
775
|
post_verify: null
|
|
680
776
|
};
|
|
681
777
|
|
|
@@ -919,12 +1015,20 @@ export async function execute(args: any, context: ServiceNowContext): Promise<To
|
|
|
919
1015
|
}
|
|
920
1016
|
}
|
|
921
1017
|
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
// ── Register flow with Flow Designer engine ─────────────────
|
|
1021
|
+
// This is the KEY step: without it, records exist but Flow Designer
|
|
1022
|
+
// shows "Your flow cannot be found" because the engine hasn't compiled it.
|
|
1023
|
+
if (flowSysId) {
|
|
1024
|
+
var engineResult = await registerFlowWithEngine(client, flowSysId, shouldActivate);
|
|
1025
|
+
diagnostics.engine_registration = {
|
|
1026
|
+
success: engineResult.success,
|
|
1027
|
+
method: engineResult.method,
|
|
1028
|
+
attempts: engineResult.attempts
|
|
1029
|
+
};
|
|
1030
|
+
if (!engineResult.success) {
|
|
1031
|
+
factoryWarnings.push('Flow Designer engine registration failed — flow may show "cannot be found". Attempts: ' + engineResult.attempts.join(', '));
|
|
928
1032
|
}
|
|
929
1033
|
}
|
|
930
1034
|
|
|
@@ -1039,7 +1143,14 @@ export async function execute(args: any, context: ServiceNowContext): Promise<To
|
|
|
1039
1143
|
createSummary.indented('Factory call: ' + (diagnostics.factory_call || 'not attempted'));
|
|
1040
1144
|
createSummary.indented('Table API used: ' + diagnostics.table_api_used);
|
|
1041
1145
|
createSummary.indented('Version created: ' + diagnostics.version_created + (diagnostics.version_method ? ' (' + diagnostics.version_method + ')' : ''));
|
|
1042
|
-
|
|
1146
|
+
if (diagnostics.engine_registration) {
|
|
1147
|
+
createSummary.indented('Engine registration: ' + (diagnostics.engine_registration.success ? diagnostics.engine_registration.method : 'FAILED'));
|
|
1148
|
+
if (diagnostics.engine_registration.attempts) {
|
|
1149
|
+
for (var ea = 0; ea < diagnostics.engine_registration.attempts.length; ea++) {
|
|
1150
|
+
createSummary.indented(' ' + diagnostics.engine_registration.attempts[ea]);
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
}
|
|
1043
1154
|
if (diagnostics.post_verify) {
|
|
1044
1155
|
if (diagnostics.post_verify.error) {
|
|
1045
1156
|
createSummary.indented('Post-verify: error — ' + diagnostics.post_verify.error);
|
|
@@ -1425,5 +1536,5 @@ export async function execute(args: any, context: ServiceNowContext): Promise<To
|
|
|
1425
1536
|
}
|
|
1426
1537
|
}
|
|
1427
1538
|
|
|
1428
|
-
export const version = '
|
|
1539
|
+
export const version = '4.0.0';
|
|
1429
1540
|
export const author = 'Snow-Flow Team';
|