@tenonhq/dovetail-servicenow 0.0.52 → 0.0.53

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/README.md CHANGED
@@ -349,6 +349,7 @@ npx dove-sn publish-flow --sys-id <sys_id> # scope defaults to the f
349
349
  # Test a flow: validate (default, read-only) or actually run it
350
350
  npx dove-sn test-flow --sys-id <sys_id> --inputs '{"phone":"+1555..."}'
351
351
  npx dove-sn test-flow --sys-id <sys_id> --execute --confirm --inputs '{...}' # runs it
352
+ npx dove-sn test-flow --sys-id <action_sys_id> --action --execute --confirm # runs an action
352
353
 
353
354
  # Edit a flow in place (rename / description / step inputs)
354
355
  echo '{"rename":{"name":"New Name"},"patchStepInputs":[{"step":"Calculate SMS Send At","input":"send_rate","value":"5"}]}' > ops.json
@@ -1160,7 +1161,14 @@ failed/timeout. Programmatic: `exportUpdateSet({ updateSet, mode })`,
1160
1161
 
1161
1162
  `test-flow` defaults to **validate** — a safe pre-flight (published? inputs match
1162
1163
  declared variables?) that never runs the flow; `--execute --confirm` runs it via
1163
- the server-side FlowAPI runner (deploy `resources/runFlow.md` first).
1164
+ the Dovetail Core `runFlow` op (`POST /api/cadso/dovetail_core/runFlow`), which
1165
+ ships with the Dovetail app — nothing to deploy. On a route-level 404 it falls
1166
+ back once to the legacy `/api/cadso/dovetail/runFlow`; `--runner <path>` is used
1167
+ as-is with no fallback. Add `--action` when `--sys-id` is a
1168
+ `sys_hub_action_type_definition` (sent as `actionSysId`). The caller needs the
1169
+ `admin` or `dovetail_user` role; a rejected run (400/403/404/422/500 with the
1170
+ op's `{ ok: false, error }`) reports `ok=false` and exits 2. Contract and source:
1171
+ [`resources/runFlow.md`](resources/runFlow.md).
1164
1172
 
1165
1173
  `edit-flow` defaults to a **dry-run** diff. With `--apply`: rename/description are
1166
1174
  written to `sys_hub_flow` through the update-set-aware API (so `--update-set` is
package/dist/cli.js CHANGED
@@ -664,15 +664,18 @@ async function runCreateFlow(flags) {
664
664
  }
665
665
  /**
666
666
  * dove-sn test-flow:
667
- * --sys-id <sys_id> Required. sys_hub_flow sys_id (flow or subflow).
667
+ * --sys-id <sys_id> Required. sys_hub_flow sys_id (flow or subflow), or a
668
+ * sys_hub_action_type_definition sys_id with --action.
669
+ * --action Optional. --sys-id is an action (sent as actionSysId).
668
670
  * --execute Optional. Actually run it (default is validate-only).
669
671
  * --confirm Required with --execute. A deliberate run-for-real gate.
670
672
  * --inputs <json> Optional. JSON object of inputs (or --inputs-json <path>).
671
673
  * --json Optional. Emit the structured TestFlowResult.
672
674
  *
673
675
  * Default (no --execute) is a safe pre-flight: published? readable? inputs match
674
- * declared variables? --execute POSTs the FlowAPI runner endpoint (see
675
- * resources/runFlow.md). Executing a flow can cause real side effects.
676
+ * declared variables? --execute POSTs the Dovetail Core runFlow op
677
+ * (/api/cadso/dovetail_core/runFlow, legacy fallback on 404; --runner overrides
678
+ * with no fallback — see resources/runFlow.md). Executing can cause real side effects.
676
679
  */
677
680
  async function runTestFlow(flags) {
678
681
  var sysId = flags["sys-id"] || flags.sysId;
@@ -690,6 +693,7 @@ async function runTestFlow(flags) {
690
693
  var params = {
691
694
  client: (0, client_1.createClient)({}),
692
695
  sysId: sysId,
696
+ target: flags.action === "true" ? "action" : "flow",
693
697
  mode: flags.execute === "true" ? "execute" : "validate",
694
698
  inputs: inputs,
695
699
  confirm: flags.confirm === "true",
package/dist/cliUsage.js CHANGED
@@ -594,14 +594,15 @@ exports.VERB_USAGE = {
594
594
  notes: ["Exit 2 when the flow was created but the snapshot did not compile (not published)."],
595
595
  },
596
596
  "test-flow": {
597
- summary: "Validate (default) or run a flow/subflow",
598
- required: [{ flag: "sys-id", value: "<sys_id>", note: "sys_hub_flow sys_id (flow or subflow)." }],
597
+ summary: "Validate (default) or run a flow/subflow/action",
598
+ required: [{ flag: "sys-id", value: "<sys_id>", note: "sys_hub_flow sys_id (flow or subflow), or an action's with --action." }],
599
599
  optional: [
600
+ { flag: "action", note: "--sys-id is a sys_hub_action_type_definition (sent as actionSysId)." },
600
601
  { flag: "execute", note: "Actually run it (default is validate-only)." },
601
602
  { flag: "confirm", note: "Required with --execute — the deliberate run-for-real gate." },
602
603
  { flag: "inputs", value: "'<json>'", note: "JSON object of flow inputs." },
603
604
  { flag: "inputs-json", value: "<path>", note: "Same, from a file." },
604
- { flag: "runner", value: "<path>", note: "Override the FlowAPI runner endpoint path." },
605
+ { flag: "runner", value: "<path>", note: "Override the runner path (default /api/cadso/dovetail_core/runFlow; no legacy fallback when set)." },
605
606
  JSON_FLAG,
606
607
  ],
607
608
  gate: "execute-confirm",
package/dist/client.d.ts CHANGED
@@ -231,4 +231,15 @@ export interface ServiceNowClient {
231
231
  }) => Promise<void>;
232
232
  };
233
233
  }
234
+ /**
235
+ * Dovetail core Scripted REST API base (ships in the Dovetail app). Every
236
+ * Dovetail server op is tried here first.
237
+ */
238
+ export declare var DOVETAIL_CORE_API_BASE: string;
239
+ /**
240
+ * Legacy global-scope Dovetail Scripted REST API base. Clients fall back to it
241
+ * once, on a 404 from DOVETAIL_CORE_API_BASE, for instances that predate the
242
+ * Dovetail app.
243
+ */
244
+ export declare var DOVETAIL_LEGACY_API_BASE: string;
234
245
  export declare function createClient(config?: ServiceNowClientConfig): ServiceNowClient;
package/dist/client.js CHANGED
@@ -24,7 +24,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
24
24
  return (mod && mod.__esModule) ? mod : { "default": mod };
25
25
  };
26
26
  Object.defineProperty(exports, "__esModule", { value: true });
27
- exports.PROCESSFLOW_PATH_PREFIX = void 0;
27
+ exports.DOVETAIL_LEGACY_API_BASE = exports.DOVETAIL_CORE_API_BASE = exports.PROCESSFLOW_PATH_PREFIX = void 0;
28
28
  exports.resolveFlowAuth = resolveFlowAuth;
29
29
  exports.isProcessflowPath = isProcessflowPath;
30
30
  exports.createClient = createClient;
@@ -134,6 +134,17 @@ function sleep(ms) {
134
134
  setTimeout(resolve, ms);
135
135
  });
136
136
  }
137
+ /**
138
+ * Dovetail core Scripted REST API base (ships in the Dovetail app). Every
139
+ * Dovetail server op is tried here first.
140
+ */
141
+ exports.DOVETAIL_CORE_API_BASE = "/api/cadso/dovetail_core/";
142
+ /**
143
+ * Legacy global-scope Dovetail Scripted REST API base. Clients fall back to it
144
+ * once, on a 404 from DOVETAIL_CORE_API_BASE, for instances that predate the
145
+ * Dovetail app.
146
+ */
147
+ exports.DOVETAIL_LEGACY_API_BASE = "/api/cadso/dovetail/";
137
148
  /**
138
149
  * Match a thrown error message against the 403/404 patterns produced by request().
139
150
  * buildAgent.* uses this to decide when to fall back to the plain Table API.
@@ -303,8 +314,8 @@ function createClient(config = {}) {
303
314
  // fall back to the legacy /api/cadso/dovetail/<op> on 404 (one-time warning).
304
315
  async function dovetailRequest(method, op, body, params, ctx) {
305
316
  var url = useDovetailLegacyPath
306
- ? "/api/cadso/dovetail/" + op
307
- : "/api/cadso/dovetail_core/" + op;
317
+ ? exports.DOVETAIL_LEGACY_API_BASE + op
318
+ : exports.DOVETAIL_CORE_API_BASE + op;
308
319
  try {
309
320
  return await request({ method: method, url: url, data: body, params: params }, ctx);
310
321
  }
@@ -312,11 +323,11 @@ function createClient(config = {}) {
312
323
  var msg = e && e.message ? String(e.message) : "";
313
324
  if (!useDovetailLegacyPath && msg.indexOf("SN 404 on") === 0) {
314
325
  // eslint-disable-next-line no-console
315
- console.warn("[deprecation] /api/cadso/dovetail_core/" + op +
316
- " returned 404. Falling back to legacy /api/cadso/dovetail/" + op +
326
+ console.warn("[deprecation] " + exports.DOVETAIL_CORE_API_BASE + op +
327
+ " returned 404. Falling back to legacy " + exports.DOVETAIL_LEGACY_API_BASE + op +
317
328
  ". Install the Dovetail application's Scripted REST APIs to silence this warning.");
318
329
  useDovetailLegacyPath = true;
319
- var legacyUrl = "/api/cadso/dovetail/" + op;
330
+ var legacyUrl = exports.DOVETAIL_LEGACY_API_BASE + op;
320
331
  return await request({ method: method, url: legacyUrl, data: body, params: params }, ctx);
321
332
  }
322
333
  throw e;
@@ -33,8 +33,8 @@ export { createFlow, buildPublishModel } from "./createFlow";
33
33
  export type { CreateFlowParams, CreateFlowResult } from "./createFlow";
34
34
  export { editFlow } from "./editFlow";
35
35
  export type { EditFlowParams, EditFlowResult, EditFlowOps, StepInputPatch } from "./editFlow";
36
- export { testFlow, DEFAULT_RUN_FLOW_PATH } from "./testFlow";
37
- export type { TestFlowParams, TestFlowResult } from "./testFlow";
36
+ export { testFlow, DEFAULT_RUN_FLOW_PATH, LEGACY_RUN_FLOW_PATH } from "./testFlow";
37
+ export type { TestFlowParams, TestFlowResult, TestFlowTarget } from "./testFlow";
38
38
  export { generateSysId, stripSystemFields, applyScope, assertSysId, SYSTEM_FIELDS_TO_STRIP, } from "./shape";
39
39
  export { topoSort, executeWritePlan, WriteOrderError } from "./writeOrder";
40
40
  export type { WriteOp, WriteOpResult } from "./writeOrder";
@@ -6,7 +6,7 @@
6
6
  * functions land in Phase 1.C/D.
7
7
  */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.canonValue = exports.toDesignerStep = exports.diffViews = exports.viewAction = exports.validateDefineSpec = exports.planActionDefinition = exports.defineActionType = exports.WriteOrderError = exports.executeWritePlan = exports.topoSort = exports.SYSTEM_FIELDS_TO_STRIP = exports.assertSysId = exports.applyScope = exports.stripSystemFields = exports.generateSysId = exports.DEFAULT_RUN_FLOW_PATH = exports.testFlow = exports.editFlow = exports.buildPublishModel = exports.createFlow = exports.copyFlow = exports.publishFlow = exports.readActionType = exports.readFlow = exports.hasStepOps = exports.findStepInput = exports.findStep = exports.formatStepPill = exports.summarizeSteps = exports.verifySteps = exports.applyStepOps = exports.editActionType = exports.publishActionType = exports.triggerPublication = exports.actionTypePath = exports.fetchActionSteps = exports.remapClonedSteps = exports.slugInternalName = exports.resolveScope = exports.cloneActionType = exports.cloneSubflow = exports.verifyArtifact = exports.listTemplates = void 0;
9
+ exports.canonValue = exports.toDesignerStep = exports.diffViews = exports.viewAction = exports.validateDefineSpec = exports.planActionDefinition = exports.defineActionType = exports.WriteOrderError = exports.executeWritePlan = exports.topoSort = exports.SYSTEM_FIELDS_TO_STRIP = exports.assertSysId = exports.applyScope = exports.stripSystemFields = exports.generateSysId = exports.LEGACY_RUN_FLOW_PATH = exports.DEFAULT_RUN_FLOW_PATH = exports.testFlow = exports.editFlow = exports.buildPublishModel = exports.createFlow = exports.copyFlow = exports.publishFlow = exports.readActionType = exports.readFlow = exports.hasStepOps = exports.findStepInput = exports.findStep = exports.formatStepPill = exports.summarizeSteps = exports.verifySteps = exports.applyStepOps = exports.editActionType = exports.publishActionType = exports.triggerPublication = exports.actionTypePath = exports.fetchActionSteps = exports.remapClonedSteps = exports.slugInternalName = exports.resolveScope = exports.cloneActionType = exports.cloneSubflow = exports.verifyArtifact = exports.listTemplates = void 0;
10
10
  var listTemplates_1 = require("./listTemplates");
11
11
  Object.defineProperty(exports, "listTemplates", { enumerable: true, get: function () { return listTemplates_1.listTemplates; } });
12
12
  var verifyArtifact_1 = require("./verifyArtifact");
@@ -51,6 +51,7 @@ Object.defineProperty(exports, "editFlow", { enumerable: true, get: function ()
51
51
  var testFlow_1 = require("./testFlow");
52
52
  Object.defineProperty(exports, "testFlow", { enumerable: true, get: function () { return testFlow_1.testFlow; } });
53
53
  Object.defineProperty(exports, "DEFAULT_RUN_FLOW_PATH", { enumerable: true, get: function () { return testFlow_1.DEFAULT_RUN_FLOW_PATH; } });
54
+ Object.defineProperty(exports, "LEGACY_RUN_FLOW_PATH", { enumerable: true, get: function () { return testFlow_1.LEGACY_RUN_FLOW_PATH; } });
54
55
  var shape_1 = require("./shape");
55
56
  Object.defineProperty(exports, "generateSysId", { enumerable: true, get: function () { return shape_1.generateSysId; } });
56
57
  Object.defineProperty(exports, "stripSystemFields", { enumerable: true, get: function () { return shape_1.stripSystemFields; } });
@@ -5,46 +5,70 @@
5
5
  *
6
6
  * mode="validate" (DEFAULT, no execution, zero risk):
7
7
  * Reads the compiled model and checks the artifact is runnable — published,
8
- * readable — and that the inputs you supplied match the flow's declared
9
- * variables (flags unknown inputs). This is the safe pre-flight you can run
10
- * anytime; it never triggers the flow.
8
+ * readable — and that the inputs you supplied match its declared variables
9
+ * (flags unknown inputs). This is the safe pre-flight you can run anytime;
10
+ * it never triggers the flow.
11
11
  *
12
12
  * mode="execute" (actually runs it):
13
- * POSTs to the server-side FlowAPI runner endpoint (a Dovetail scoped
14
- * Scripted REST resource that calls sn_fd.FlowAPI.getRunner(...).run() /
15
- * .startAsync() — see resources/runFlow.md for the deployable source). The
16
- * UI "Test" button has no guessable native REST route, so this server-side
17
- * runner is the supported, uniform path across flow | subflow | action.
13
+ * POSTs to the Dovetail Core `runFlow` Scripted REST op
14
+ * (/api/cadso/dovetail_core/runFlow), which ships with the Dovetail app and
15
+ * calls sn_fd.FlowAPI.getRunner().flow|subflow|action(name).inForeground()
16
+ * .withInputs(inputs).run() — see resources/runFlow.md. The UI "Test" button
17
+ * has no guessable native REST route, so this server-side runner is the
18
+ * supported, uniform path across flow | subflow | action.
18
19
  * Execution is GUARDED: you must pass mode="execute" AND confirm=true.
19
20
  *
21
+ * Path resolution mirrors the client's Dovetail core → legacy fallback: the
22
+ * Dovetail Core path is tried first; a route-level 404 (the op itself is not
23
+ * installed) falls back ONCE to the legacy global path /api/cadso/dovetail/runFlow.
24
+ * An explicit `runnerPath` always wins and never falls back.
25
+ *
20
26
  * Executing a flow can cause real side effects (the example subflow sends an
21
27
  * SMS). Prefer mode="validate"; gate mode="execute" behind a sandbox flow.
22
28
  */
23
29
  import type { ServiceNowClient } from "../client";
24
- /** Default runner endpoint — a Dovetail scoped Scripted REST resource. */
30
+ /** Default runner endpoint — the Dovetail Core runFlow op (ships with the Dovetail app). */
25
31
  export declare var DEFAULT_RUN_FLOW_PATH: string;
32
+ /** Legacy global-scope runner path, tried once when the default path 404s. */
33
+ export declare var LEGACY_RUN_FLOW_PATH: string;
34
+ /** What `sysId` points at: a sys_hub_flow (flow or subflow) or a sys_hub_action_type_definition. */
35
+ export type TestFlowTarget = "flow" | "action";
26
36
  export interface TestFlowParams {
27
37
  client: ServiceNowClient;
28
- /** sys_id of the sys_hub_flow (flow or subflow). */
38
+ /**
39
+ * sys_id of the artifact to test: a sys_hub_flow (flow or subflow) when
40
+ * target="flow" (default), or a sys_hub_action_type_definition when
41
+ * target="action".
42
+ */
29
43
  sysId: string;
44
+ /** "flow" (default — sys_hub_flow, sent as flowSysId) or "action" (sent as actionSysId). */
45
+ target?: TestFlowTarget;
30
46
  /** "validate" (default — no execution) or "execute" (runs it; requires confirm). */
31
47
  mode?: "validate" | "execute";
32
- /** Inputs passed to the flow. Keys should match declared flow-variable names. */
33
- inputs?: Record<string, any>;
48
+ /** Inputs passed to the flow/action. Keys should match declared input names. */
49
+ inputs?: Record<string, unknown>;
34
50
  /** Required to be true for mode="execute" — a deliberate run-this-for-real gate. */
35
51
  confirm?: boolean;
36
- /** Override the runner endpoint path (defaults to DEFAULT_RUN_FLOW_PATH). */
52
+ /**
53
+ * Override the runner endpoint path. When set it is used as-is with NO
54
+ * fallback; when omitted, DEFAULT_RUN_FLOW_PATH is tried, then
55
+ * LEGACY_RUN_FLOW_PATH once on a route-level 404.
56
+ */
37
57
  runnerPath?: string;
38
58
  }
39
59
  export interface TestFlowResult {
40
60
  mode: "validate" | "execute";
41
- /** Whether the artifact is runnable / the run was accepted. */
61
+ /** Whether the artifact is runnable / the run succeeded. */
42
62
  ok: boolean;
43
63
  /** Human-readable findings (validation notes, run status). */
44
64
  notes: Array<string>;
45
65
  /** For execute mode: the run context sys_id, when the runner returns one. */
46
66
  contextSysId?: string;
47
- /** For execute mode: the raw runner response. */
48
- run?: any;
67
+ /** For execute mode: the HTTP status the runner answered with. */
68
+ httpStatus?: number;
69
+ /** For execute mode: the runner path that answered. */
70
+ runnerPath?: string;
71
+ /** For execute mode: the raw (unwrapped) runner response. */
72
+ run?: unknown;
49
73
  }
50
74
  export declare function testFlow(params: TestFlowParams): Promise<TestFlowResult>;
@@ -6,38 +6,89 @@
6
6
  *
7
7
  * mode="validate" (DEFAULT, no execution, zero risk):
8
8
  * Reads the compiled model and checks the artifact is runnable — published,
9
- * readable — and that the inputs you supplied match the flow's declared
10
- * variables (flags unknown inputs). This is the safe pre-flight you can run
11
- * anytime; it never triggers the flow.
9
+ * readable — and that the inputs you supplied match its declared variables
10
+ * (flags unknown inputs). This is the safe pre-flight you can run anytime;
11
+ * it never triggers the flow.
12
12
  *
13
13
  * mode="execute" (actually runs it):
14
- * POSTs to the server-side FlowAPI runner endpoint (a Dovetail scoped
15
- * Scripted REST resource that calls sn_fd.FlowAPI.getRunner(...).run() /
16
- * .startAsync() — see resources/runFlow.md for the deployable source). The
17
- * UI "Test" button has no guessable native REST route, so this server-side
18
- * runner is the supported, uniform path across flow | subflow | action.
14
+ * POSTs to the Dovetail Core `runFlow` Scripted REST op
15
+ * (/api/cadso/dovetail_core/runFlow), which ships with the Dovetail app and
16
+ * calls sn_fd.FlowAPI.getRunner().flow|subflow|action(name).inForeground()
17
+ * .withInputs(inputs).run() — see resources/runFlow.md. The UI "Test" button
18
+ * has no guessable native REST route, so this server-side runner is the
19
+ * supported, uniform path across flow | subflow | action.
19
20
  * Execution is GUARDED: you must pass mode="execute" AND confirm=true.
20
21
  *
22
+ * Path resolution mirrors the client's Dovetail core → legacy fallback: the
23
+ * Dovetail Core path is tried first; a route-level 404 (the op itself is not
24
+ * installed) falls back ONCE to the legacy global path /api/cadso/dovetail/runFlow.
25
+ * An explicit `runnerPath` always wins and never falls back.
26
+ *
21
27
  * Executing a flow can cause real side effects (the example subflow sends an
22
28
  * SMS). Prefer mode="validate"; gate mode="execute" behind a sandbox flow.
23
29
  */
24
30
  Object.defineProperty(exports, "__esModule", { value: true });
25
- exports.DEFAULT_RUN_FLOW_PATH = void 0;
31
+ exports.LEGACY_RUN_FLOW_PATH = exports.DEFAULT_RUN_FLOW_PATH = void 0;
26
32
  exports.testFlow = testFlow;
33
+ const client_1 = require("../client");
27
34
  const readFlow_1 = require("./readFlow");
28
- /** Default runner endpoint — a Dovetail scoped Scripted REST resource. */
29
- exports.DEFAULT_RUN_FLOW_PATH = "/api/cadso/dovetail/runFlow";
35
+ const readActionType_1 = require("./readActionType");
36
+ /** Default runner endpoint — the Dovetail Core runFlow op (ships with the Dovetail app). */
37
+ exports.DEFAULT_RUN_FLOW_PATH = client_1.DOVETAIL_CORE_API_BASE + "runFlow";
38
+ /** Legacy global-scope runner path, tried once when the default path 404s. */
39
+ exports.LEGACY_RUN_FLOW_PATH = client_1.DOVETAIL_LEGACY_API_BASE + "runFlow";
40
+ var SYS_ID_RE = /^[0-9a-f]{32}$/;
41
+ function isRecord(value) {
42
+ return value !== null && typeof value === "object" && !Array.isArray(value);
43
+ }
44
+ /** ServiceNow wraps a Scripted REST op's return value in { result: ... }. */
30
45
  function unwrap(data) {
31
- if (data && typeof data === "object" && data.result && typeof data.result === "object") {
46
+ if (isRecord(data) && isRecord(data.result)) {
32
47
  return data.result;
33
48
  }
34
49
  return data;
35
50
  }
36
- /** Validate-mode pre-flight: published? readable? inputs recognized? */
37
- async function validate(params) {
51
+ /**
52
+ * True when a response body is the runFlow op's own { ok, ... } contract. Used
53
+ * to tell "the op answered 404 because the sys_id is unknown" (no fallback)
54
+ * from "the route itself does not exist" (fall back / not deployed).
55
+ */
56
+ function isRunnerContract(body) {
57
+ var data = unwrap(body);
58
+ return isRecord(data) && typeof data.ok === "boolean";
59
+ }
60
+ function bodySnippet(body) {
61
+ if (body === undefined || body === null)
62
+ return "";
63
+ var text = typeof body === "string" ? body : JSON.stringify(body);
64
+ return text.length > 400 ? text.substring(0, 400) + "…" : text;
65
+ }
66
+ /** Table API reference fields come back as a sys_id string or { value }. */
67
+ function refValue(field) {
68
+ if (typeof field === "string")
69
+ return field;
70
+ if (isRecord(field) && typeof field.value === "string")
71
+ return field.value;
72
+ return "";
73
+ }
74
+ function checkInputs(inputs, declaredNames, noun, notes) {
75
+ var declared = {};
76
+ for (var v = 0; v < declaredNames.length; v += 1) {
77
+ declared[declaredNames[v]] = true;
78
+ }
79
+ var keys = Object.keys(inputs);
80
+ for (var i = 0; i < keys.length; i += 1) {
81
+ if (!declared[keys[i]]) {
82
+ notes.push("warning: input '" + keys[i] + "' does not match any declared " + noun + ".");
83
+ }
84
+ }
85
+ notes.push(keys.length + " input(s) supplied; " + declaredNames.length + " " + noun + "(s) declared.");
86
+ }
87
+ /** Validate-mode pre-flight for a flow/subflow: published? readable? inputs recognized? */
88
+ async function validateFlow(params, sysId) {
38
89
  var notes = [];
39
90
  var ok = true;
40
- var read = await (0, readFlow_1.readFlow)({ client: params.client, sysId: params.sysId });
91
+ var read = await (0, readFlow_1.readFlow)({ client: params.client, sysId: sysId });
41
92
  notes.push("flow: " + read.name + " (" + read.type + ")");
42
93
  if (!read.published) {
43
94
  ok = false;
@@ -49,65 +100,138 @@ async function validate(params) {
49
100
  if (!read.userCanRead) {
50
101
  notes.push("warning: userCanRead is false for the integration user.");
51
102
  }
52
- var inputs = params.inputs || {};
53
- var declared = {};
103
+ var names = [];
54
104
  for (var v = 0; v < read.variables.length; v += 1) {
55
- declared[read.variables[v].name] = true;
105
+ names.push(read.variables[v].name);
56
106
  }
57
- var keys = Object.keys(inputs);
58
- for (var i = 0; i < keys.length; i += 1) {
59
- if (!declared[keys[i]]) {
60
- notes.push("warning: input '" + keys[i] + "' does not match any declared flow variable.");
61
- }
107
+ checkInputs(params.inputs || {}, names, "flow variable", notes);
108
+ return { mode: "validate", ok: ok, notes: notes };
109
+ }
110
+ /**
111
+ * Validate-mode pre-flight for an action: the record exists and has the
112
+ * internal_name the runner addresses it by, and the supplied inputs match the
113
+ * action's declared inputs.
114
+ */
115
+ async function validateAction(params, sysId) {
116
+ var notes = [];
117
+ var rows = await params.client.table.query("sys_hub_action_type_definition", "sys_id=" + sysId, { limit: 1, fields: ["sys_id", "name", "internal_name", "sys_scope"] });
118
+ var row = rows && rows.length > 0 ? rows[0] : undefined;
119
+ if (!row) {
120
+ notes.push("action not found: sys_hub_action_type_definition " + sysId);
121
+ return { mode: "validate", ok: false, notes: notes };
122
+ }
123
+ var name = typeof row.name === "string" ? row.name : "";
124
+ var internalName = typeof row.internal_name === "string" ? row.internal_name : "";
125
+ notes.push("action: " + (name || sysId));
126
+ var ok = true;
127
+ if (!internalName) {
128
+ ok = false;
129
+ notes.push("NO internal_name — the runner addresses actions by <scope>.<internal_name>, so it cannot run.");
130
+ }
131
+ var scopeSysId = refValue(row.sys_scope);
132
+ if (!scopeSysId) {
133
+ notes.push("warning: could not resolve the action's scope; inputs were not checked.");
134
+ return { mode: "validate", ok: ok, notes: notes };
62
135
  }
63
- notes.push(keys.length + " input(s) supplied; " + read.variables.length + " variable(s) declared.");
136
+ var read = await (0, readActionType_1.readActionType)({ client: params.client, sysId: sysId, scopeSysId: scopeSysId });
137
+ var names = [];
138
+ for (var i = 0; i < read.inputs.length; i += 1) {
139
+ names.push(read.inputs[i].name);
140
+ }
141
+ checkInputs(params.inputs || {}, names, "action input", notes);
142
+ notes.push("note: publish state is not checked for actions.");
64
143
  return { mode: "validate", ok: ok, notes: notes };
65
144
  }
145
+ function postRunner(client, path, body) {
146
+ return client.now.invoke({ method: "POST", path: path, body: body });
147
+ }
66
148
  /** Execute-mode: POST the runner endpoint. Requires confirm=true. */
67
- async function execute(params) {
149
+ async function execute(params, sysId) {
68
150
  if (params.confirm !== true) {
69
151
  throw new Error("testFlow: mode='execute' requires confirm=true — running a flow can cause real "
70
152
  + "side effects (e.g. sending an SMS). Pass confirm:true to proceed.");
71
153
  }
72
- var path = params.runnerPath || exports.DEFAULT_RUN_FLOW_PATH;
73
- var body = {
74
- flowSysId: params.sysId,
75
- inputs: params.inputs || {}
76
- };
77
- var resp;
78
- try {
79
- resp = await params.client.now.post(path, body);
80
- }
81
- catch (err) {
82
- var msg = err && err.message ? String(err.message) : String(err);
83
- if (msg.indexOf("404") >= 0) {
84
- throw new Error("testFlow: the runner endpoint " + path + " is not deployed. Deploy the FlowAPI "
85
- + "Scripted REST resource (see resources/runFlow.md) or pass runnerPath to an "
86
- + "existing one.");
87
- }
88
- throw err;
154
+ var body = { inputs: params.inputs || {} };
155
+ if (params.target === "action") {
156
+ body.actionSysId = sysId;
157
+ }
158
+ else {
159
+ body.flowSysId = sysId;
89
160
  }
90
- var data = unwrap(resp);
161
+ var isExplicit = typeof params.runnerPath === "string" && params.runnerPath.length > 0;
162
+ var path = isExplicit ? String(params.runnerPath) : exports.DEFAULT_RUN_FLOW_PATH;
163
+ var tried = [path];
164
+ var resp = await postRunner(params.client, path, body);
165
+ if (!isExplicit && resp.status === 404 && !isRunnerContract(resp.body)) {
166
+ // Same core → legacy fallback the client uses for every Dovetail op.
167
+ // eslint-disable-next-line no-console
168
+ console.warn("[deprecation] " + exports.DEFAULT_RUN_FLOW_PATH + " returned 404. Falling back to legacy "
169
+ + exports.LEGACY_RUN_FLOW_PATH + ". Install the Dovetail application to silence this warning.");
170
+ path = exports.LEGACY_RUN_FLOW_PATH;
171
+ tried.push(path);
172
+ resp = await postRunner(params.client, path, body);
173
+ }
174
+ var status = resp.status;
175
+ var isContract = isRunnerContract(resp.body);
176
+ if (status === 404 && !isContract) {
177
+ throw new Error("testFlow: no runFlow endpoint found (tried " + tried.join(", ") + "). The runFlow op "
178
+ + "ships with the Dovetail app under Dovetail Core — install or upgrade the Dovetail "
179
+ + "app on this instance, or pass runnerPath to an existing runner.");
180
+ }
181
+ if ((status < 200 || status >= 300) && !isContract) {
182
+ var hint = status === 401 || status === 403
183
+ ? " — check the integration user's credentials and that it holds the admin or dovetail_user role."
184
+ : "";
185
+ throw new Error("testFlow: runner " + path + " returned HTTP " + status + hint
186
+ + (bodySnippet(resp.body) ? ": " + bodySnippet(resp.body) : ""));
187
+ }
188
+ var data = unwrap(resp.body);
189
+ var record = isRecord(data) ? data : {};
91
190
  var contextSysId;
92
- if (data && typeof data === "object") {
93
- contextSysId = typeof data.contextId === "string" ? data.contextId
94
- : (typeof data.context_sys_id === "string" ? data.context_sys_id : undefined);
191
+ if (typeof record.contextId === "string" && record.contextId) {
192
+ contextSysId = record.contextId;
193
+ }
194
+ else if (typeof record.context_sys_id === "string" && record.context_sys_id) {
195
+ contextSysId = record.context_sys_id;
196
+ }
197
+ var ok = status >= 200 && status < 300 && record.ok !== false;
198
+ var notes = [];
199
+ if (ok) {
200
+ notes.push("run completed via " + path
201
+ + (typeof record.name === "string" && record.name ? " (" + record.name + ")" : ""));
202
+ }
203
+ else {
204
+ var reason = typeof record.error === "string" && record.error ? record.error : "no error message";
205
+ var roleHint = status === 403 ? " (the caller needs the admin or dovetail_user role)" : "";
206
+ notes.push("run rejected by " + path + " (HTTP " + status + ")" + roleHint + ": " + reason);
95
207
  }
96
208
  return {
97
209
  mode: "execute",
98
- ok: true,
99
- notes: ["run accepted via " + path],
210
+ ok: ok,
211
+ notes: notes,
100
212
  contextSysId: contextSysId,
213
+ httpStatus: status,
214
+ runnerPath: path,
101
215
  run: data
102
216
  };
103
217
  }
104
218
  async function testFlow(params) {
105
- if (!params.sysId) {
219
+ if (!params || !params.sysId) {
106
220
  throw new Error("testFlow: sysId is required.");
107
221
  }
222
+ var sysId = String(params.sysId).trim().toLowerCase();
223
+ if (!SYS_ID_RE.test(sysId)) {
224
+ throw new Error("testFlow: sysId must be a 32-character hex sys_id (got '" + params.sysId + "').");
225
+ }
226
+ if (params.target !== undefined && params.target !== "flow" && params.target !== "action") {
227
+ throw new Error("testFlow: target must be 'flow' or 'action'.");
228
+ }
108
229
  var mode = params.mode || "validate";
109
230
  if (mode === "execute") {
110
- return execute(params);
231
+ return execute(params, sysId);
232
+ }
233
+ if (params.target === "action") {
234
+ return validateAction(params, sysId);
111
235
  }
112
- return validate(params);
236
+ return validateFlow(params, sysId);
113
237
  }
package/dist/index.d.ts CHANGED
@@ -18,8 +18,8 @@ export { setFormLayout } from "./layout/formLayout";
18
18
  export { setRelatedLists } from "./layout/relatedLists";
19
19
  export { formatLayoutResult, formatCreateViewResult } from "./layout/formatter";
20
20
  export { sincPlugin } from "./plugin";
21
- export { listTemplates, verifyArtifact, cloneSubflow, cloneActionType, resolveScope, slugInternalName, fetchActionSteps, findStepInput, triggerPublication, publishActionType, editActionType, defineActionType, planActionDefinition, validateDefineSpec, applyStepOps, verifySteps, summarizeSteps, formatStepPill, readFlow, readActionType, publishFlow, copyFlow, createFlow, buildPublishModel, editFlow, testFlow, DEFAULT_RUN_FLOW_PATH, generateSysId, topoSort, executeWritePlan, WriteOrderError, } from "./flowDesigner";
22
- export type { TemplateRef, ListTemplatesParams, FlowKind, VerifyExpect, VerifyFound, VerifyFailure, VerifyReport, VerifyArtifactParams, CloneSubflowParams, CloneSubflowResult, CloneActionTypeParams, CloneActionTypeResult, CloneActionTypePlan, CloneActionTypeStepReport, TriggerPublicationParams, TriggerPublicationResult, PublishActionTypeParams, PublishActionTypeResult, EditActionTypeParams, EditActionTypeResult, EditActionTypeOps, DefineActionSpec, DefineActionInputSpec, DefineActionOutputSpec, DefineStepSpec, DefineStepVarSpec, DefineStepOutputSpec, DefineStepValue, DefineActionTypeParams, DefineActionTypeResult, DefineActionDiff, DefineActionPlan, PlanActionDefinitionParams, ActionView, StepView, StepOps, StepRecord, StepSummary, StepIoSummary, PatchStepScriptOp, SetStepInputOp, AddStepOutputOp, AddStepInputOp, ApplyStepOpsResult, VerifyStepsResult, ReadFlowParams, ReadFlowResult, FlowStep, FlowVariable, ReadActionTypeParams, ReadActionTypeResult, ActionIo, PublishFlowParams, PublishFlowResult, CopyFlowParams, CopyFlowResult, CreateFlowParams, CreateFlowResult, EditFlowParams, EditFlowResult, EditFlowOps, StepInputPatch, TestFlowParams, TestFlowResult, WriteOp, WriteOpResult, } from "./flowDesigner";
21
+ export { listTemplates, verifyArtifact, cloneSubflow, cloneActionType, resolveScope, slugInternalName, fetchActionSteps, findStepInput, triggerPublication, publishActionType, editActionType, defineActionType, planActionDefinition, validateDefineSpec, applyStepOps, verifySteps, summarizeSteps, formatStepPill, readFlow, readActionType, publishFlow, copyFlow, createFlow, buildPublishModel, editFlow, testFlow, DEFAULT_RUN_FLOW_PATH, LEGACY_RUN_FLOW_PATH, generateSysId, topoSort, executeWritePlan, WriteOrderError, } from "./flowDesigner";
22
+ export type { TemplateRef, ListTemplatesParams, FlowKind, VerifyExpect, VerifyFound, VerifyFailure, VerifyReport, VerifyArtifactParams, CloneSubflowParams, CloneSubflowResult, CloneActionTypeParams, CloneActionTypeResult, CloneActionTypePlan, CloneActionTypeStepReport, TriggerPublicationParams, TriggerPublicationResult, PublishActionTypeParams, PublishActionTypeResult, EditActionTypeParams, EditActionTypeResult, EditActionTypeOps, DefineActionSpec, DefineActionInputSpec, DefineActionOutputSpec, DefineStepSpec, DefineStepVarSpec, DefineStepOutputSpec, DefineStepValue, DefineActionTypeParams, DefineActionTypeResult, DefineActionDiff, DefineActionPlan, PlanActionDefinitionParams, ActionView, StepView, StepOps, StepRecord, StepSummary, StepIoSummary, PatchStepScriptOp, SetStepInputOp, AddStepOutputOp, AddStepInputOp, ApplyStepOpsResult, VerifyStepsResult, ReadFlowParams, ReadFlowResult, FlowStep, FlowVariable, ReadActionTypeParams, ReadActionTypeResult, ActionIo, PublishFlowParams, PublishFlowResult, CopyFlowParams, CopyFlowResult, CreateFlowParams, CreateFlowResult, EditFlowParams, EditFlowResult, EditFlowOps, StepInputPatch, TestFlowParams, TestFlowResult, TestFlowTarget, WriteOp, WriteOpResult, } from "./flowDesigner";
23
23
  export type { ServiceNowClientConfig, ChoiceValue, ChoiceType, AddChoicesParams, AddChoicesResult, ChoiceActionResult, ChoiceFieldRef, RemoveChoicesParams, RemoveChoicesResult, ChoiceRemovalResult, DictionaryRecord, UpdateSetRecord, LayoutAction, LayoutRecordResult, LayoutResult, CreateViewParams, CreateViewResult, FormSectionSpec, SetFormLayoutParams, SetListLayoutParams, SetRelatedListsParams, ChunkRole, ChunkInfo, ChunkResult, PrunedResult, HostAssetsParams, HostAssetsResult, } from "./types";
24
24
  export { createTable, projectTableGraph, buildColumnXml, normalizeColumns, resolveType, applyTableSaveOverlay, defaultAccessFlags, TYPE_MAP, DEFAULT_SUPER_CLASS, DEFAULT_SAVE_ACTION, addColumn, deriveElement, ensureDesignAccess, findDesignAccess, DESIGN_ACCESS_TABLE, addIndex, parseIndexColumns, indexMatchesColumns, listIndexes, createIndex, validateCreateIndex, captureRowName, parseAjaxAnswer, parseCanCreate, buildCanCreateFields, buildCreateScheduleFields, XMLHTTP_PATH, DEFAULT_ACCESS_METHOD, CAPTURE_NOTE, setColumn, resolveAttributes, toStoredValue, setTable, resolveTableAttributes, } from "./table";
25
25
  export type { CreateTableParams, CreateTableResult, AddColumnParams, AddColumnResult, DesignAccessFlag, EnsureDesignAccessParams, EnsureDesignAccessResult, AddIndexParams, AddIndexResult, AddIndexVerification, ListIndexesParams, ListIndexesResult, TableIndex, CreateIndexParams, CreateIndexResult, SetColumnParams, SetColumnResult, ColumnAttributes, AttributeChange, SetTableParams, SetTableResult, TableAttributes, TableGraph, NormalizedColumn, ColumnSpec, AccessFlags, OverlaySpec, } from "./table";
package/dist/index.js CHANGED
@@ -7,9 +7,9 @@
7
7
  */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.editFlow = exports.buildPublishModel = exports.createFlow = exports.copyFlow = exports.publishFlow = exports.readActionType = exports.readFlow = exports.formatStepPill = exports.summarizeSteps = exports.verifySteps = exports.applyStepOps = exports.validateDefineSpec = exports.planActionDefinition = exports.defineActionType = exports.editActionType = exports.publishActionType = exports.triggerPublication = exports.findStepInput = exports.fetchActionSteps = exports.slugInternalName = exports.resolveScope = exports.cloneActionType = exports.cloneSubflow = exports.verifyArtifact = exports.listTemplates = exports.sincPlugin = exports.formatCreateViewResult = exports.formatLayoutResult = exports.setRelatedLists = exports.setFormLayout = exports.setListLayout = exports.createView = exports.formatRemoveChoicesResult = exports.formatAddChoicesResult = exports.formatHostAssetsResult = exports.classifyChunks = exports.hostAssets = exports.ChoiceWriteError = exports.removeChoicesFromField = exports.addChoicesToField = exports.resolveConfigFromEnvFile = exports.createClientFromEnvFile = exports.assertWriteAllowed = exports.evaluateWriteGate = exports.isCiEnvironment = exports.resolveExecutionContext = exports.PROCESSFLOW_PATH_PREFIX = exports.isProcessflowPath = exports.resolveFlowAuth = exports.createClient = void 0;
10
- exports.verifyReadBack = exports.readBackMatches = exports.hasHtmlEntity = exports.decodeHtmlEntities = exports.formatUxEventSync = exports.parseNowUiActions = exports.syncUxEvents = exports.deleteRecord = exports.createRecord = exports.setField = exports.resolveTableAttributes = exports.setTable = exports.toStoredValue = exports.resolveAttributes = exports.setColumn = exports.CAPTURE_NOTE = exports.DEFAULT_ACCESS_METHOD = exports.XMLHTTP_PATH = exports.buildCreateScheduleFields = exports.buildCanCreateFields = exports.parseCanCreate = exports.parseAjaxAnswer = exports.captureRowName = exports.validateCreateIndex = exports.createIndex = exports.listIndexes = exports.indexMatchesColumns = exports.parseIndexColumns = exports.addIndex = exports.DESIGN_ACCESS_TABLE = exports.findDesignAccess = exports.ensureDesignAccess = exports.deriveElement = exports.addColumn = exports.DEFAULT_SAVE_ACTION = exports.DEFAULT_SUPER_CLASS = exports.TYPE_MAP = exports.defaultAccessFlags = exports.applyTableSaveOverlay = exports.resolveType = exports.normalizeColumns = exports.buildColumnXml = exports.projectTableGraph = exports.createTable = exports.WriteOrderError = exports.executeWritePlan = exports.topoSort = exports.generateSysId = exports.DEFAULT_RUN_FLOW_PATH = exports.testFlow = void 0;
11
- exports.defaultSecretRules = exports.escapeRegExp = exports.encodeXmlText = exports.encodeXmlEntities = exports.stripJsonValue = exports.stripField = exports.plannedStrips = exports.recordFieldNames = exports.readRecordTable = exports.readField = exports.verifyStripped = exports.stripSecrets = exports.DEFAULT_EXPORT_APP_TIMEOUT_MS = exports.buildPublishFields = exports.buildCreateSetFields = exports.exportApp = exports.DEFAULT_MAX_ROWS = exports.MAX_PAGE_SIZE = exports.DEFAULT_PAGE_SIZE = exports.UPDATE_XML_FIELDS = exports.xmlEscape = exports.formatUnloadDate = exports.parseStatsCount = exports.refreshTypeFields = exports.fetchUpdateXmlRows = exports.countUpdateXml = exports.countUnloadRecords = exports.renderUnload = exports.renderRemoteUpdateSet = exports.renderUpdateXmlRow = exports.exportUpdateSet = exports.PUBLISH_POLL_DELAYS_MS = exports.DEFAULT_PUBLISH_TIMEOUT_MS = exports.parseCicdProgress = exports.parseCicdPublishResponse = exports.harvestProgressResults = exports.flattenSteps = exports.classifyProgress = exports.parseProgressTree = exports.parseXmlAnswer = exports.PUBLISH_TARGETS = exports.parsePublishTargets = exports.describeTarget = exports.resolveUpdateSetNaming = exports.buildPublishToUpdateSetFields = exports.buildCreateUpdateSetFields = exports.buildStartFields = exports.publishApp = exports.INVOKE_REST_METHODS = exports.invokeRest = void 0;
12
- exports.SECRET_INTERNAL_TYPES = exports.SENTINEL = exports.isCapturable = exports.secretFieldsFromDictionary = exports.mergeSecretRules = exports.loadSecretRules = void 0;
10
+ exports.readBackMatches = exports.hasHtmlEntity = exports.decodeHtmlEntities = exports.formatUxEventSync = exports.parseNowUiActions = exports.syncUxEvents = exports.deleteRecord = exports.createRecord = exports.setField = exports.resolveTableAttributes = exports.setTable = exports.toStoredValue = exports.resolveAttributes = exports.setColumn = exports.CAPTURE_NOTE = exports.DEFAULT_ACCESS_METHOD = exports.XMLHTTP_PATH = exports.buildCreateScheduleFields = exports.buildCanCreateFields = exports.parseCanCreate = exports.parseAjaxAnswer = exports.captureRowName = exports.validateCreateIndex = exports.createIndex = exports.listIndexes = exports.indexMatchesColumns = exports.parseIndexColumns = exports.addIndex = exports.DESIGN_ACCESS_TABLE = exports.findDesignAccess = exports.ensureDesignAccess = exports.deriveElement = exports.addColumn = exports.DEFAULT_SAVE_ACTION = exports.DEFAULT_SUPER_CLASS = exports.TYPE_MAP = exports.defaultAccessFlags = exports.applyTableSaveOverlay = exports.resolveType = exports.normalizeColumns = exports.buildColumnXml = exports.projectTableGraph = exports.createTable = exports.WriteOrderError = exports.executeWritePlan = exports.topoSort = exports.generateSysId = exports.LEGACY_RUN_FLOW_PATH = exports.DEFAULT_RUN_FLOW_PATH = exports.testFlow = void 0;
11
+ exports.escapeRegExp = exports.encodeXmlText = exports.encodeXmlEntities = exports.stripJsonValue = exports.stripField = exports.plannedStrips = exports.recordFieldNames = exports.readRecordTable = exports.readField = exports.verifyStripped = exports.stripSecrets = exports.DEFAULT_EXPORT_APP_TIMEOUT_MS = exports.buildPublishFields = exports.buildCreateSetFields = exports.exportApp = exports.DEFAULT_MAX_ROWS = exports.MAX_PAGE_SIZE = exports.DEFAULT_PAGE_SIZE = exports.UPDATE_XML_FIELDS = exports.xmlEscape = exports.formatUnloadDate = exports.parseStatsCount = exports.refreshTypeFields = exports.fetchUpdateXmlRows = exports.countUpdateXml = exports.countUnloadRecords = exports.renderUnload = exports.renderRemoteUpdateSet = exports.renderUpdateXmlRow = exports.exportUpdateSet = exports.PUBLISH_POLL_DELAYS_MS = exports.DEFAULT_PUBLISH_TIMEOUT_MS = exports.parseCicdProgress = exports.parseCicdPublishResponse = exports.harvestProgressResults = exports.flattenSteps = exports.classifyProgress = exports.parseProgressTree = exports.parseXmlAnswer = exports.PUBLISH_TARGETS = exports.parsePublishTargets = exports.describeTarget = exports.resolveUpdateSetNaming = exports.buildPublishToUpdateSetFields = exports.buildCreateUpdateSetFields = exports.buildStartFields = exports.publishApp = exports.INVOKE_REST_METHODS = exports.invokeRest = exports.verifyReadBack = void 0;
12
+ exports.SECRET_INTERNAL_TYPES = exports.SENTINEL = exports.isCapturable = exports.secretFieldsFromDictionary = exports.mergeSecretRules = exports.loadSecretRules = exports.defaultSecretRules = void 0;
13
13
  var client_1 = require("./client");
14
14
  Object.defineProperty(exports, "createClient", { enumerable: true, get: function () { return client_1.createClient; } });
15
15
  Object.defineProperty(exports, "resolveFlowAuth", { enumerable: true, get: function () { return client_1.resolveFlowAuth; } });
@@ -75,6 +75,7 @@ Object.defineProperty(exports, "buildPublishModel", { enumerable: true, get: fun
75
75
  Object.defineProperty(exports, "editFlow", { enumerable: true, get: function () { return flowDesigner_1.editFlow; } });
76
76
  Object.defineProperty(exports, "testFlow", { enumerable: true, get: function () { return flowDesigner_1.testFlow; } });
77
77
  Object.defineProperty(exports, "DEFAULT_RUN_FLOW_PATH", { enumerable: true, get: function () { return flowDesigner_1.DEFAULT_RUN_FLOW_PATH; } });
78
+ Object.defineProperty(exports, "LEGACY_RUN_FLOW_PATH", { enumerable: true, get: function () { return flowDesigner_1.LEGACY_RUN_FLOW_PATH; } });
78
79
  Object.defineProperty(exports, "generateSysId", { enumerable: true, get: function () { return flowDesigner_1.generateSysId; } });
79
80
  Object.defineProperty(exports, "topoSort", { enumerable: true, get: function () { return flowDesigner_1.topoSort; } });
80
81
  Object.defineProperty(exports, "executeWritePlan", { enumerable: true, get: function () { return flowDesigner_1.executeWritePlan; } });
@@ -396,13 +396,17 @@ function buildDescriptors(deps = {}) {
396
396
  "pre-flight — checks the flow is published and that supplied inputs match its declared " +
397
397
  "variables; it never runs the flow. mode='execute' actually runs it via the server-side " +
398
398
  "FlowAPI runner and REQUIRES confirm=true (running a flow can cause real side effects, " +
399
- "e.g. sending an SMS). sysId is the sys_hub_flow sys_id.",
399
+ "e.g. sending an SMS). sysId is the sys_hub_flow sys_id, or a sys_hub_action_type_definition " +
400
+ "sys_id with target='action'. Execute POSTs /api/cadso/dovetail_core/runFlow (ships with the " +
401
+ "Dovetail app; falls back once to the legacy /api/cadso/dovetail/runFlow on a 404); an " +
402
+ "explicit runnerPath is used as-is.",
400
403
  shape: schemas_1.testFlowSchema.shape,
401
404
  handler: async function (args) {
402
405
  var p = schemas_1.testFlowSchema.parse(args);
403
406
  return (0, testFlow_1.testFlow)({
404
407
  client: client(),
405
408
  sysId: p.sysId,
409
+ target: p.target,
406
410
  mode: p.mode,
407
411
  inputs: p.inputs,
408
412
  confirm: p.confirm,
@@ -291,18 +291,21 @@ export declare var createFlowSchema: z.ZodObject<{
291
291
  }>;
292
292
  export declare var testFlowSchema: z.ZodObject<{
293
293
  sysId: z.ZodString;
294
+ target: z.ZodOptional<z.ZodUnion<[z.ZodLiteral<"flow">, z.ZodLiteral<"action">]>>;
294
295
  mode: z.ZodOptional<z.ZodUnion<[z.ZodLiteral<"validate">, z.ZodLiteral<"execute">]>>;
295
296
  inputs: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
296
297
  confirm: z.ZodOptional<z.ZodBoolean>;
297
298
  runnerPath: z.ZodOptional<z.ZodString>;
298
299
  }, "strip", z.ZodTypeAny, {
299
300
  sysId: string;
301
+ target?: "action" | "flow" | undefined;
300
302
  confirm?: boolean | undefined;
301
303
  mode?: "execute" | "validate" | undefined;
302
304
  inputs?: Record<string, any> | undefined;
303
305
  runnerPath?: string | undefined;
304
306
  }, {
305
307
  sysId: string;
308
+ target?: "action" | "flow" | undefined;
306
309
  confirm?: boolean | undefined;
307
310
  mode?: "execute" | "validate" | undefined;
308
311
  inputs?: Record<string, any> | undefined;
@@ -103,6 +103,7 @@ exports.createFlowSchema = zod_1.z.object({
103
103
  });
104
104
  exports.testFlowSchema = zod_1.z.object({
105
105
  sysId: zod_1.z.string().min(1),
106
+ target: zod_1.z.union([zod_1.z.literal("flow"), zod_1.z.literal("action")]).optional(),
106
107
  mode: zod_1.z.union([zod_1.z.literal("validate"), zod_1.z.literal("execute")]).optional(),
107
108
  inputs: zod_1.z.record(zod_1.z.any()).optional(),
108
109
  confirm: zod_1.z.boolean().optional(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tenonhq/dovetail-servicenow",
3
- "version": "0.0.52",
3
+ "version": "0.0.53",
4
4
  "engines": {
5
5
  "node": ">=22"
6
6
  },