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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package.json",
3
- "version": "10.0.1-test.110",
3
+ "version": "10.0.1-test.111",
4
4
  "name": "snow-flow-test",
5
5
  "description": "Snow-Flow Test - ServiceNow Multi-Agent Development Framework",
6
6
  "license": "Elastic-2.0",
@@ -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
- ' try { body = JSON.parse(request.body.dataString); }',
52
- ' catch(e) { body = request.body.data; }',
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: "Invalid request body: " + typeof body });',
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
- snapshot_result: null,
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
- // Best-effort snapshot
923
- try {
924
- await client.post('/api/sn_flow_designer/flow/snapshot', { flow_id: flowSysId });
925
- diagnostics.snapshot_result = 'success';
926
- } catch (snapError: any) {
927
- diagnostics.snapshot_result = 'error: ' + (snapError.response?.status || snapError.message || 'unknown');
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
- createSummary.indented('Snapshot: ' + (diagnostics.snapshot_result || 'n/a'));
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 = '3.0.0';
1539
+ export const version = '4.0.0';
1429
1540
  export const author = 'Snow-Flow Team';