callman-core 1.18.0 → 1.20.0
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/host/db/connectionMapping.d.ts +4 -0
- package/dist/host/db/connectionMapping.d.ts.map +1 -1
- package/dist/host/db/connectionMapping.js +4 -0
- package/dist/host/db/connectionMapping.js.map +1 -1
- package/dist/host/db/pgClientConfig.d.ts +11 -0
- package/dist/host/db/pgClientConfig.d.ts.map +1 -0
- package/dist/host/db/pgClientConfig.js +83 -0
- package/dist/host/db/pgClientConfig.js.map +1 -0
- package/dist/host/db/pgSessionManager.d.ts +18 -0
- package/dist/host/db/pgSessionManager.d.ts.map +1 -0
- package/dist/host/db/pgSessionManager.js +162 -0
- package/dist/host/db/pgSessionManager.js.map +1 -0
- package/dist/host/db/postgresAdapter.d.ts.map +1 -1
- package/dist/host/db/postgresAdapter.js +7 -36
- package/dist/host/db/postgresAdapter.js.map +1 -1
- package/dist/host/db/queryExecutor.d.ts +4 -0
- package/dist/host/db/queryExecutor.d.ts.map +1 -1
- package/dist/host/db/queryExecutor.js +40 -2
- package/dist/host/db/queryExecutor.js.map +1 -1
- package/dist/host/db/sqlState.d.ts +2 -0
- package/dist/host/db/sqlState.d.ts.map +1 -0
- package/dist/host/db/sqlState.js +14 -0
- package/dist/host/db/sqlState.js.map +1 -0
- package/dist/host/db/types.d.ts +13 -0
- package/dist/host/db/types.d.ts.map +1 -1
- package/dist/host/index.d.ts +3 -0
- package/dist/host/index.d.ts.map +1 -1
- package/dist/host/index.js +7 -0
- package/dist/host/index.js.map +1 -1
- package/dist/scenario-runner/adapters/connection-config.d.ts +4 -0
- package/dist/scenario-runner/adapters/connection-config.d.ts.map +1 -1
- package/dist/scenario-runner/adapters/db-executor.d.ts +7 -1
- package/dist/scenario-runner/adapters/db-executor.d.ts.map +1 -1
- package/dist/scenario-runner/adapters/db-executor.js +106 -1
- package/dist/scenario-runner/adapters/db-executor.js.map +1 -1
- package/dist/scenario-runner/adapters/index.d.ts +2 -1
- package/dist/scenario-runner/adapters/index.d.ts.map +1 -1
- package/dist/scenario-runner/adapters/index.js +11 -1
- package/dist/scenario-runner/adapters/index.js.map +1 -1
- package/dist/scenario-runner/adapters/types.d.ts +9 -0
- package/dist/scenario-runner/adapters/types.d.ts.map +1 -1
- package/dist/scenario-runner/adapters/websocket-executor.d.ts +4 -0
- package/dist/scenario-runner/adapters/websocket-executor.d.ts.map +1 -0
- package/dist/scenario-runner/adapters/websocket-executor.js +20 -0
- package/dist/scenario-runner/adapters/websocket-executor.js.map +1 -0
- package/dist/scenario-runner/condition.d.ts +1 -0
- package/dist/scenario-runner/condition.d.ts.map +1 -1
- package/dist/scenario-runner/condition.js +138 -2
- package/dist/scenario-runner/condition.js.map +1 -1
- package/dist/scenario-runner/conditionTypes.d.ts +1 -1
- package/dist/scenario-runner/conditionTypes.d.ts.map +1 -1
- package/dist/scenario-runner/graphTraversal.d.ts +8 -0
- package/dist/scenario-runner/graphTraversal.d.ts.map +1 -1
- package/dist/scenario-runner/graphTraversal.js +9 -0
- package/dist/scenario-runner/graphTraversal.js.map +1 -1
- package/dist/scenario-runner/index.d.ts +1 -0
- package/dist/scenario-runner/index.d.ts.map +1 -1
- package/dist/scenario-runner/index.js +1 -0
- package/dist/scenario-runner/index.js.map +1 -1
- package/dist/scenario-runner/nodePolicy.d.ts +2 -2
- package/dist/scenario-runner/nodePolicy.d.ts.map +1 -1
- package/dist/scenario-runner/nodePolicy.js +2 -0
- package/dist/scenario-runner/nodePolicy.js.map +1 -1
- package/dist/scenario-runner/runScenario.d.ts.map +1 -1
- package/dist/scenario-runner/runScenario.js +202 -2
- package/dist/scenario-runner/runScenario.js.map +1 -1
- package/dist/scenario-runner/types.d.ts +142 -3
- package/dist/scenario-runner/types.d.ts.map +1 -1
- package/dist/scenario-runner/websocket.d.ts +17 -0
- package/dist/scenario-runner/websocket.d.ts.map +1 -0
- package/dist/scenario-runner/websocket.js +74 -0
- package/dist/scenario-runner/websocket.js.map +1 -0
- package/dist-cjs/host/db/connectionMapping.js +4 -0
- package/dist-cjs/host/db/connectionMapping.js.map +1 -1
- package/dist-cjs/host/db/pgClientConfig.js +90 -0
- package/dist-cjs/host/db/pgClientConfig.js.map +1 -0
- package/dist-cjs/host/db/pgSessionManager.js +170 -0
- package/dist-cjs/host/db/pgSessionManager.js.map +1 -0
- package/dist-cjs/host/db/postgresAdapter.js +7 -36
- package/dist-cjs/host/db/postgresAdapter.js.map +1 -1
- package/dist-cjs/host/db/queryExecutor.js +40 -2
- package/dist-cjs/host/db/queryExecutor.js.map +1 -1
- package/dist-cjs/host/db/sqlState.js +18 -0
- package/dist-cjs/host/db/sqlState.js.map +1 -0
- package/dist-cjs/host/index.js +16 -1
- package/dist-cjs/host/index.js.map +1 -1
- package/dist-cjs/scenario-runner/adapters/db-executor.js +108 -2
- package/dist-cjs/scenario-runner/adapters/db-executor.js.map +1 -1
- package/dist-cjs/scenario-runner/adapters/index.js +14 -1
- package/dist-cjs/scenario-runner/adapters/index.js.map +1 -1
- package/dist-cjs/scenario-runner/adapters/websocket-executor.js +24 -0
- package/dist-cjs/scenario-runner/adapters/websocket-executor.js.map +1 -0
- package/dist-cjs/scenario-runner/condition.js +140 -3
- package/dist-cjs/scenario-runner/condition.js.map +1 -1
- package/dist-cjs/scenario-runner/graphTraversal.js +10 -1
- package/dist-cjs/scenario-runner/graphTraversal.js.map +1 -1
- package/dist-cjs/scenario-runner/index.js +1 -0
- package/dist-cjs/scenario-runner/index.js.map +1 -1
- package/dist-cjs/scenario-runner/nodePolicy.js +2 -0
- package/dist-cjs/scenario-runner/nodePolicy.js.map +1 -1
- package/dist-cjs/scenario-runner/runScenario.js +201 -1
- package/dist-cjs/scenario-runner/runScenario.js.map +1 -1
- package/dist-cjs/scenario-runner/websocket.js +79 -0
- package/dist-cjs/scenario-runner/websocket.js.map +1 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/scenario-runner/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EACL,2BAA2B,EAC3B,2BAA2B,EAC3B,6BAA6B,EAC7B,0BAA0B,EAC1B,8CAA8C,EAC9C,iCAAiC,EACjC,6BAA6B,GAC9B,MAAM,uBAAuB,CAAC;AAM/B,cAAc,gBAAgB,CAAC;AAE/B,cAAc,iBAAiB,CAAC;AAGhC,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EACL,gCAAgC,EAChC,0BAA0B,GAC3B,MAAM,yBAAyB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/scenario-runner/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EACL,2BAA2B,EAC3B,2BAA2B,EAC3B,6BAA6B,EAC7B,0BAA0B,EAC1B,8CAA8C,EAC9C,iCAAiC,EACjC,6BAA6B,GAC9B,MAAM,uBAAuB,CAAC;AAM/B,cAAc,gBAAgB,CAAC;AAE/B,cAAc,iBAAiB,CAAC;AAGhC,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EACL,gCAAgC,EAChC,0BAA0B,GAC3B,MAAM,yBAAyB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/scenario-runner/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EACL,2BAA2B,EAC3B,2BAA2B,EAC3B,6BAA6B,EAC7B,0BAA0B,EAC1B,8CAA8C,EAC9C,iCAAiC,EACjC,6BAA6B,GAC9B,MAAM,uBAAuB,CAAC;AAC/B,iEAAiE;AACjE,qEAAqE;AACrE,uEAAuE;AACvE,uEAAuE;AACvE,iCAAiC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,2EAA2E;AAC3E,cAAc,iBAAiB,CAAC;AAChC,sEAAsE;AACtE,oEAAoE;AACpE,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EACL,gCAAgC,EAChC,0BAA0B,GAC3B,MAAM,yBAAyB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/scenario-runner/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EACL,2BAA2B,EAC3B,2BAA2B,EAC3B,6BAA6B,EAC7B,0BAA0B,EAC1B,8CAA8C,EAC9C,iCAAiC,EACjC,6BAA6B,GAC9B,MAAM,uBAAuB,CAAC;AAC/B,iEAAiE;AACjE,qEAAqE;AACrE,uEAAuE;AACvE,uEAAuE;AACvE,iCAAiC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,2EAA2E;AAC3E,cAAc,iBAAiB,CAAC;AAChC,sEAAsE;AACtE,oEAAoE;AACpE,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EACL,gCAAgC,EAChC,0BAA0B,GAC3B,MAAM,yBAAyB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AggregatorScenarioNode, DbScenarioNode, EndScenarioNode, KafkaScenarioNode, NotificationScenarioNode, RedisScenarioNode, RequestScenarioNode, ScenarioNode, ScenarioNodeExecutionPolicy, ScenarioPolicyCapableNode, ScenarioPolicyCapableNodeType, ScriptScenarioNode, SubScenarioNode, ForeachScenarioNode, WaitScenarioNode } from "./types.js";
|
|
1
|
+
import { AggregatorScenarioNode, DbScenarioNode, EndScenarioNode, KafkaScenarioNode, NotificationScenarioNode, RedisScenarioNode, RequestScenarioNode, ScenarioNode, ScenarioNodeExecutionPolicy, ScenarioPolicyCapableNode, ScenarioPolicyCapableNodeType, ScriptScenarioNode, SubScenarioNode, ForeachScenarioNode, WebsocketScenarioNode, WaitScenarioNode } from "./types.js";
|
|
2
2
|
export declare const STRICT_SCENARIO_NODE_EXECUTION_POLICY: ScenarioNodeExecutionPolicy;
|
|
3
3
|
export declare const supportsScenarioNodeExecutionPolicy: (nodeOrType: ScenarioNode | ScenarioPolicyCapableNodeType) => nodeOrType is ScenarioPolicyCapableNode | ScenarioPolicyCapableNodeType;
|
|
4
4
|
export declare const normalizeScenarioNodeExecutionPolicy: (value: unknown, fallback?: ScenarioNodeExecutionPolicy) => ScenarioNodeExecutionPolicy;
|
|
@@ -7,5 +7,5 @@ export declare const getNewScenarioNodeExecutionPolicyPreset: (type: ScenarioPol
|
|
|
7
7
|
export declare const getScenarioNodeExecutionPolicy: (node: ScenarioPolicyCapableNode) => ScenarioNodeExecutionPolicy;
|
|
8
8
|
export declare const getScenarioNodeMaxAttempts: (policy: ScenarioNodeExecutionPolicy) => number;
|
|
9
9
|
export declare const getScenarioNodePolicyBadges: (node: ScenarioPolicyCapableNode) => string[];
|
|
10
|
-
export declare const patchScenarioNodeExecutionPolicy: <TNode extends RequestScenarioNode | DbScenarioNode | WaitScenarioNode | ScriptScenarioNode | KafkaScenarioNode | RedisScenarioNode | NotificationScenarioNode | EndScenarioNode | AggregatorScenarioNode | SubScenarioNode | ForeachScenarioNode>(node: TNode, executionPolicy: ScenarioNodeExecutionPolicy) => TNode;
|
|
10
|
+
export declare const patchScenarioNodeExecutionPolicy: <TNode extends RequestScenarioNode | DbScenarioNode | WaitScenarioNode | ScriptScenarioNode | KafkaScenarioNode | RedisScenarioNode | NotificationScenarioNode | EndScenarioNode | AggregatorScenarioNode | SubScenarioNode | ForeachScenarioNode | WebsocketScenarioNode>(node: TNode, executionPolicy: ScenarioNodeExecutionPolicy) => TNode;
|
|
11
11
|
//# sourceMappingURL=nodePolicy.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nodePolicy.d.ts","sourceRoot":"","sources":["../../src/scenario-runner/nodePolicy.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EACtB,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,wBAAwB,EACxB,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,EACZ,2BAA2B,EAC3B,yBAAyB,EACzB,6BAA6B,EAC7B,kBAAkB,EAClB,eAAe,EACf,mBAAmB,EACnB,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAEpB,eAAO,MAAM,qCAAqC,EAAE,2BAOnD,CAAC;
|
|
1
|
+
{"version":3,"file":"nodePolicy.d.ts","sourceRoot":"","sources":["../../src/scenario-runner/nodePolicy.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EACtB,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,wBAAwB,EACxB,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,EACZ,2BAA2B,EAC3B,yBAAyB,EACzB,6BAA6B,EAC7B,kBAAkB,EAClB,eAAe,EACf,mBAAmB,EACnB,qBAAqB,EACrB,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAEpB,eAAO,MAAM,qCAAqC,EAAE,2BAOnD,CAAC;AA8DF,eAAO,MAAM,mCAAmC,GAC9C,YAAY,YAAY,GAAG,6BAA6B,KACvD,UAAU,IAAI,yBAAyB,GAAG,6BAI5C,CAAC;AAEF,eAAO,MAAM,oCAAoC,GAC/C,OAAO,OAAO,EACd,WAAU,2BAAmE,KAC5E,2BA+DF,CAAC;AAEF,eAAO,MAAM,oCAAoC,QAAO,2BACJ,CAAC;AAErD,eAAO,MAAM,uCAAuC,GAClD,MAAM,6BAA6B,KAClC,2BAAqF,CAAC;AAEzF,eAAO,MAAM,8BAA8B,GACzC,MAAM,yBAAyB,KAC9B,2BAIA,CAAC;AAEJ,eAAO,MAAM,0BAA0B,GACrC,QAAQ,2BAA2B,KAClC,MAA4E,CAAC;AAEhF,eAAO,MAAM,2BAA2B,GACtC,MAAM,yBAAyB,KAC9B,MAAM,EAeR,CAAC;AAEF,eAAO,MAAM,gCAAgC,GAC3C,KAAK,SACD,mBAAmB,GACnB,cAAc,GACd,gBAAgB,GAChB,kBAAkB,GAClB,iBAAiB,GACjB,iBAAiB,GACjB,wBAAwB,GACxB,eAAe,GACf,sBAAsB,GACtB,eAAe,GACf,mBAAmB,GACnB,qBAAqB,EAEzB,MAAM,KAAK,EACX,iBAAiB,2BAA2B,KAC3C,KASD,CAAC"}
|
|
@@ -48,6 +48,8 @@ const RECOMMENDED_NEW_NODE_POLICY_PRESETS = {
|
|
|
48
48
|
// The item loop IS the repeat mechanism for this node type — retry stays
|
|
49
49
|
// off (and is force-disabled at execution time in runScenario).
|
|
50
50
|
foreach: STRICT_SCENARIO_NODE_EXECUTION_POLICY,
|
|
51
|
+
// Retry re-runs the WHOLE conversation (connect -> steps -> close).
|
|
52
|
+
websocket: STRICT_SCENARIO_NODE_EXECUTION_POLICY,
|
|
51
53
|
};
|
|
52
54
|
const clonePolicy = (policy) => ({
|
|
53
55
|
onFailure: policy.onFailure,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nodePolicy.js","sourceRoot":"","sources":["../../src/scenario-runner/nodePolicy.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"nodePolicy.js","sourceRoot":"","sources":["../../src/scenario-runner/nodePolicy.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runScenario.d.ts","sourceRoot":"","sources":["../../src/scenario-runner/runScenario.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"runScenario.d.ts","sourceRoot":"","sources":["../../src/scenario-runner/runScenario.ts"],"names":[],"mappings":"AAyDA,OAAO,KAAK,EAKV,kBAAkB,EAUlB,iBAAiB,EAKlB,MAAM,YAAY,CAAC;AAyuBpB,eAAO,MAAM,WAAW,GAAU,mGAQ/B,kBAAkB,KAAG,OAAO,CAAC,iBAAiB,CAs9EhD,CAAC"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { buildConditionOutputPayload, evaluateConditionConfig, evaluateConditionRule, resolveConditionRuntimeValue, validateConditionConfig, } from "./condition.js";
|
|
2
2
|
import { applyExtract } from "./extraction.js";
|
|
3
3
|
import { evaluateAssertionConfig, validateAssertionConfig, } from "./assertion.js";
|
|
4
|
-
import { createSubScenarioStepId, buildRuntimeStepDescriptors, DEFAULT_END_LOOP_DELAY_MS, DEFAULT_END_LOOP_ITERATIONS, flattenScenarioNodesForContext, MAX_END_LOOP_ITERATIONS, DEFAULT_POLL_INTERVAL_MS, DEFAULT_POLL_MAX_ATTEMPTS, MAX_POLL_ATTEMPTS, DEFAULT_FOREACH_MAX_ITERATIONS, MAX_FOREACH_ITERATIONS, } from "./graphTraversal.js";
|
|
4
|
+
import { createSubScenarioStepId, buildRuntimeStepDescriptors, DEFAULT_END_LOOP_DELAY_MS, DEFAULT_END_LOOP_ITERATIONS, flattenScenarioNodesForContext, MAX_END_LOOP_ITERATIONS, DEFAULT_POLL_INTERVAL_MS, DEFAULT_POLL_MAX_ATTEMPTS, MAX_POLL_ATTEMPTS, DEFAULT_FOREACH_MAX_ITERATIONS, MAX_FOREACH_ITERATIONS, DEFAULT_WS_CONNECT_TIMEOUT_MS, MAX_WS_CONNECT_TIMEOUT_MS, DEFAULT_WS_EXPECT_TIMEOUT_MS, MAX_WS_EXPECT_TIMEOUT_MS, MAX_WS_WAIT_DURATION_MS, MAX_WS_STEPS, DEFAULT_WS_CLOSE_CODE, } from "./graphTraversal.js";
|
|
5
|
+
import { evaluateWebsocketExpect } from "./websocket.js";
|
|
5
6
|
import { executeWithScenarioNodePolicy } from "./executionPolicyRunner.js";
|
|
6
7
|
import { getLegacyScenarioNodeExecutionPolicy, getScenarioNodeExecutionPolicy, supportsScenarioNodeExecutionPolicy, } from "./nodePolicy.js";
|
|
7
8
|
import { buildScenarioExecutionGraph, buildScenarioTemplateValues, collectExclusiveBranchNodeIds, evaluateScenarioExpression, resolveScenarioJsonTemplateString, resolveScenarioTemplateString, } from "./templateResolver.js";
|
|
@@ -44,6 +45,7 @@ const RESERVED_WORKFLOW_ROOT_LABELS = new Set([
|
|
|
44
45
|
"item",
|
|
45
46
|
"each",
|
|
46
47
|
"eaches",
|
|
48
|
+
"ws",
|
|
47
49
|
]);
|
|
48
50
|
const cloneNodeExecutionMeta = (meta) => ({
|
|
49
51
|
...meta,
|
|
@@ -998,13 +1000,36 @@ export const runScenario = async ({ scenario, environment = {}, globals = {}, ru
|
|
|
998
1000
|
}
|
|
999
1001
|
if (node.type === "db") {
|
|
1000
1002
|
const resolvedQuery = resolveScenarioTemplateString(node.data.config.query, templateValues);
|
|
1001
|
-
|
|
1003
|
+
// Typed params win over legacy `params`. Types encode into the
|
|
1004
|
+
// wire value here so drivers stay oblivious: `null` → SQL NULL,
|
|
1005
|
+
// `boolean` → real boolean; everything else stays a string and
|
|
1006
|
+
// relies on server-side casts (see DbScenarioParamType docs).
|
|
1007
|
+
const typedParams = node.data.config.typedParams;
|
|
1008
|
+
const resolvedParams = typedParams
|
|
1009
|
+
? typedParams.map((param) => {
|
|
1010
|
+
if (param.type === "null")
|
|
1011
|
+
return null;
|
|
1012
|
+
const resolved = resolveScenarioTemplateString(param.value ?? "", templateValues);
|
|
1013
|
+
if (param.type === "boolean") {
|
|
1014
|
+
return ["true", "1", "t", "yes"].includes(resolved.trim().toLowerCase());
|
|
1015
|
+
}
|
|
1016
|
+
return resolved;
|
|
1017
|
+
})
|
|
1018
|
+
: (node.data.config.params ?? []).map((param) => resolveScenarioTemplateString(param, templateValues));
|
|
1002
1019
|
const dbResult = await runtimeAdapters.dbExecutor({
|
|
1003
1020
|
runId,
|
|
1004
1021
|
stepId,
|
|
1005
1022
|
node,
|
|
1006
1023
|
resolvedQuery,
|
|
1007
1024
|
resolvedParams,
|
|
1025
|
+
...(node.data.config.useSession
|
|
1026
|
+
? {
|
|
1027
|
+
session: {
|
|
1028
|
+
runId,
|
|
1029
|
+
transactionMode: scenario.dbSettings?.transactionMode ?? "none",
|
|
1030
|
+
},
|
|
1031
|
+
}
|
|
1032
|
+
: {}),
|
|
1008
1033
|
context: createContextSnapshot(runtimeContext),
|
|
1009
1034
|
signal,
|
|
1010
1035
|
});
|
|
@@ -1445,6 +1470,163 @@ export const runScenario = async ({ scenario, environment = {}, globals = {}, ru
|
|
|
1445
1470
|
outputData = runtimeContext.kafkaEvent;
|
|
1446
1471
|
}
|
|
1447
1472
|
}
|
|
1473
|
+
if (node.type === "websocket") {
|
|
1474
|
+
const wsConfig = node.data.config;
|
|
1475
|
+
const resolvedUrl = resolveScenarioTemplateString(wsConfig.url ?? "", templateValues).trim();
|
|
1476
|
+
if (!resolvedUrl) {
|
|
1477
|
+
throw new ScenarioNodeFailureError("WebSocket URL is required.");
|
|
1478
|
+
}
|
|
1479
|
+
const configuredSteps = wsConfig.steps ?? [];
|
|
1480
|
+
if (configuredSteps.length > MAX_WS_STEPS) {
|
|
1481
|
+
throw new ScenarioNodeFailureError(`WebSocket conversations are capped at ${MAX_WS_STEPS} steps.`);
|
|
1482
|
+
}
|
|
1483
|
+
for (const [stepIndex, step] of configuredSteps.entries()) {
|
|
1484
|
+
if (step.kind === "expect" && (!step.rules || step.rules.length === 0)) {
|
|
1485
|
+
throw new ScenarioNodeFailureError(`WebSocket expect step ${stepIndex + 1} has no rules.`);
|
|
1486
|
+
}
|
|
1487
|
+
}
|
|
1488
|
+
const resolvedHeaders = (wsConfig.headers ?? [])
|
|
1489
|
+
.filter((header) => header.enabled !== false && header.key.trim())
|
|
1490
|
+
.map((header) => ({
|
|
1491
|
+
key: resolveScenarioTemplateString(header.key, templateValues).trim(),
|
|
1492
|
+
value: resolveScenarioTemplateString(header.value ?? "", templateValues),
|
|
1493
|
+
}));
|
|
1494
|
+
const resolvedSubprotocols = (wsConfig.subprotocols ?? [])
|
|
1495
|
+
.map((protocol) => resolveScenarioTemplateString(protocol, templateValues).trim())
|
|
1496
|
+
.filter((protocol) => protocol.length > 0);
|
|
1497
|
+
const connectTimeoutMs = Math.min(MAX_WS_CONNECT_TIMEOUT_MS, Math.max(100, Math.round(wsConfig.connectTimeoutMs ?? DEFAULT_WS_CONNECT_TIMEOUT_MS)));
|
|
1498
|
+
const resolvedSteps = configuredSteps.map((step) => {
|
|
1499
|
+
if (step.kind === "send") {
|
|
1500
|
+
return {
|
|
1501
|
+
id: step.id,
|
|
1502
|
+
kind: "send",
|
|
1503
|
+
payload: resolveScenarioJsonTemplateString(step.payload ?? "", templateValues),
|
|
1504
|
+
};
|
|
1505
|
+
}
|
|
1506
|
+
if (step.kind === "wait") {
|
|
1507
|
+
return {
|
|
1508
|
+
id: step.id,
|
|
1509
|
+
kind: "wait",
|
|
1510
|
+
durationMs: Math.min(MAX_WS_WAIT_DURATION_MS, Math.max(0, Math.round(step.durationMs ?? 0))),
|
|
1511
|
+
};
|
|
1512
|
+
}
|
|
1513
|
+
return {
|
|
1514
|
+
id: step.id,
|
|
1515
|
+
kind: "expect",
|
|
1516
|
+
timeoutMs: Math.min(MAX_WS_EXPECT_TIMEOUT_MS, Math.max(100, Math.round(step.timeoutMs ?? DEFAULT_WS_EXPECT_TIMEOUT_MS))),
|
|
1517
|
+
matchMode: step.matchMode === "any" ? "any" : "all",
|
|
1518
|
+
rules: step.rules,
|
|
1519
|
+
};
|
|
1520
|
+
});
|
|
1521
|
+
const wsExecution = await runtimeAdapters.websocketExecutor({
|
|
1522
|
+
runId,
|
|
1523
|
+
stepId,
|
|
1524
|
+
node,
|
|
1525
|
+
resolvedUrl,
|
|
1526
|
+
resolvedHeaders,
|
|
1527
|
+
subprotocols: resolvedSubprotocols,
|
|
1528
|
+
connectTimeoutMs,
|
|
1529
|
+
steps: resolvedSteps,
|
|
1530
|
+
closeCode: wsConfig.closeCode ?? DEFAULT_WS_CLOSE_CODE,
|
|
1531
|
+
rejectUnauthorized: wsConfig.rejectUnauthorized !== false,
|
|
1532
|
+
environment: { ...runtimeContext.environment },
|
|
1533
|
+
globals: { ...runtimeContext.globals },
|
|
1534
|
+
signal,
|
|
1535
|
+
});
|
|
1536
|
+
throwIfStopped(signal);
|
|
1537
|
+
// Authoritative expect evaluation over the recorded frames — the
|
|
1538
|
+
// host's early-stop is advisory only (kafka consume precedent).
|
|
1539
|
+
const evaluationScope = {
|
|
1540
|
+
environment: runtimeContext.environment,
|
|
1541
|
+
globals: runtimeContext.globals,
|
|
1542
|
+
workflowContext: runtimeContext.workflowContext,
|
|
1543
|
+
nodeMetaByLabel: runtimeContext.nodeMetaByLabel,
|
|
1544
|
+
responseRoot: runtimeContext.responseRoot,
|
|
1545
|
+
dbResult: runtimeContext.dbResult,
|
|
1546
|
+
kafkaEvent: runtimeContext.kafkaEvent,
|
|
1547
|
+
redisResult: runtimeContext.redisResult,
|
|
1548
|
+
};
|
|
1549
|
+
const outcomesByIndex = new Map(wsExecution.stepOutcomes.map((outcome) => [outcome.index, outcome]));
|
|
1550
|
+
let conversationBroken = !wsExecution.connected;
|
|
1551
|
+
const stepResults = resolvedSteps.map((step, index) => {
|
|
1552
|
+
const outcome = outcomesByIndex.get(index);
|
|
1553
|
+
const durationMs = outcome && outcome.startedAt && outcome.endedAt
|
|
1554
|
+
? Math.max(0, new Date(outcome.endedAt).getTime() - new Date(outcome.startedAt).getTime())
|
|
1555
|
+
: 0;
|
|
1556
|
+
if (!outcome) {
|
|
1557
|
+
return {
|
|
1558
|
+
index,
|
|
1559
|
+
kind: step.kind,
|
|
1560
|
+
status: "failed",
|
|
1561
|
+
durationMs: 0,
|
|
1562
|
+
error: conversationBroken
|
|
1563
|
+
? "Step not reached — the conversation ended early."
|
|
1564
|
+
: "Step was not executed by the host.",
|
|
1565
|
+
matchedMessageIndex: null,
|
|
1566
|
+
};
|
|
1567
|
+
}
|
|
1568
|
+
if (step.kind !== "expect") {
|
|
1569
|
+
const failed = Boolean(outcome.error);
|
|
1570
|
+
if (failed)
|
|
1571
|
+
conversationBroken = true;
|
|
1572
|
+
return {
|
|
1573
|
+
index,
|
|
1574
|
+
kind: step.kind,
|
|
1575
|
+
status: failed ? "failed" : "passed",
|
|
1576
|
+
durationMs,
|
|
1577
|
+
error: outcome.error ?? null,
|
|
1578
|
+
matchedMessageIndex: null,
|
|
1579
|
+
};
|
|
1580
|
+
}
|
|
1581
|
+
const candidates = wsExecution.messages.filter((message) => message.direction === "received" && message.stepIndex === index);
|
|
1582
|
+
let matchedMessageIndex = null;
|
|
1583
|
+
for (const candidate of candidates) {
|
|
1584
|
+
const evaluation = evaluateWebsocketExpect(step.rules ?? [], step.matchMode ?? "all", evaluationScope, candidate);
|
|
1585
|
+
if (evaluation.passed) {
|
|
1586
|
+
matchedMessageIndex = candidate.index;
|
|
1587
|
+
break;
|
|
1588
|
+
}
|
|
1589
|
+
}
|
|
1590
|
+
const failed = matchedMessageIndex === null;
|
|
1591
|
+
if (failed)
|
|
1592
|
+
conversationBroken = true;
|
|
1593
|
+
return {
|
|
1594
|
+
index,
|
|
1595
|
+
kind: step.kind,
|
|
1596
|
+
status: failed ? "failed" : "passed",
|
|
1597
|
+
durationMs,
|
|
1598
|
+
error: failed
|
|
1599
|
+
? (outcome.error ??
|
|
1600
|
+
`No message matched within ${step.timeoutMs}ms (${candidates.length} received).`)
|
|
1601
|
+
: null,
|
|
1602
|
+
matchedMessageIndex,
|
|
1603
|
+
};
|
|
1604
|
+
});
|
|
1605
|
+
const failedSteps = stepResults.filter((entry) => entry.status === "failed").length;
|
|
1606
|
+
const wsErrorMessage = !wsExecution.connected
|
|
1607
|
+
? (wsExecution.connectError ?? "WebSocket connection failed.")
|
|
1608
|
+
: failedSteps > 0
|
|
1609
|
+
? (() => {
|
|
1610
|
+
const firstFailed = stepResults.find((entry) => entry.status === "failed");
|
|
1611
|
+
return `WebSocket step ${(firstFailed?.index ?? 0) + 1} (${firstFailed?.kind}) failed: ${firstFailed?.error}`;
|
|
1612
|
+
})()
|
|
1613
|
+
: null;
|
|
1614
|
+
outputData = {
|
|
1615
|
+
url: resolvedUrl,
|
|
1616
|
+
connected: wsExecution.connected,
|
|
1617
|
+
closeCode: wsExecution.closeCode,
|
|
1618
|
+
closeReason: wsExecution.closeReason ?? null,
|
|
1619
|
+
durationMs: wsExecution.durationMs,
|
|
1620
|
+
messageCount: wsExecution.messages.length,
|
|
1621
|
+
messages: wsExecution.messages,
|
|
1622
|
+
steps: stepResults,
|
|
1623
|
+
failedSteps,
|
|
1624
|
+
errorMessage: wsErrorMessage,
|
|
1625
|
+
};
|
|
1626
|
+
if (wsErrorMessage) {
|
|
1627
|
+
throw new ScenarioNodeFailureError(wsErrorMessage);
|
|
1628
|
+
}
|
|
1629
|
+
}
|
|
1448
1630
|
if (node.type === "condition") {
|
|
1449
1631
|
const conditionIssues = validateConditionConfig(node.data.config);
|
|
1450
1632
|
const blockingConditionIssue = conditionIssues.find((issue) => issue.severity === "error");
|
|
@@ -2384,6 +2566,24 @@ export const runScenario = async ({ scenario, environment = {}, globals = {}, ru
|
|
|
2384
2566
|
workflowMeta,
|
|
2385
2567
|
});
|
|
2386
2568
|
}
|
|
2569
|
+
// Release the run's DB sessions (COMMIT/ROLLBACK + connection teardown).
|
|
2570
|
+
// Runs after BOTH outcome paths so `rollback` mode is honored even when
|
|
2571
|
+
// the scenario failed or was stopped mid-transaction. Cleanup must never
|
|
2572
|
+
// mask the run result, hence the swallow-with-log catch.
|
|
2573
|
+
if (runtimeAdapters.dbSessionRelease) {
|
|
2574
|
+
const commitAllowed = scenario.dbSettings?.transactionMode === "commit" &&
|
|
2575
|
+
finalStatus !== "failed" &&
|
|
2576
|
+
finalStatus !== "stopped";
|
|
2577
|
+
try {
|
|
2578
|
+
await runtimeAdapters.dbSessionRelease({
|
|
2579
|
+
runId,
|
|
2580
|
+
outcome: commitAllowed ? "commit" : "rollback",
|
|
2581
|
+
});
|
|
2582
|
+
}
|
|
2583
|
+
catch {
|
|
2584
|
+
// Session teardown failure is not allowed to change the run outcome.
|
|
2585
|
+
}
|
|
2586
|
+
}
|
|
2387
2587
|
const endedAt = new Date().toISOString();
|
|
2388
2588
|
const finalWorkflowMeta = updateWorkflowMetaState({
|
|
2389
2589
|
context: runtimeContext,
|