@boboddy/sdk 0.3.1 → 0.4.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/client.js +36 -23
- package/dist/definitions/advancement-policies/cohort-advancement-policy.d.ts +117 -0
- package/dist/definitions/advancement-policies/cohort-fluent-rules.d.ts +126 -0
- package/dist/definitions/advancement-policies/index.d.ts +2 -0
- package/dist/definitions/advancement-policies/index.js +242 -0
- package/dist/definitions/pipelines/builder-helpers.d.ts +39 -8
- package/dist/definitions/pipelines/builder.d.ts +50 -44
- package/dist/definitions/pipelines/chain-graph.d.ts +19 -0
- package/dist/definitions/pipelines/define-default-pipeline-assignment.d.ts +3 -3
- package/dist/definitions/pipelines/define-pipeline.d.ts +106 -13
- package/dist/definitions/pipelines/fan-out-builder.d.ts +66 -0
- package/dist/definitions/pipelines/index.js +510 -125
- package/dist/definitions/pipelines/pipeline-definitions-client.d.ts +6 -6
- package/dist/definitions/steps/define-step.d.ts +7 -3
- package/dist/definitions/steps/index.js +36 -23
- package/dist/definitions/validation/index.js +91 -22
- package/dist/generated/index.d.ts +1 -1
- package/dist/generated/sdk.gen.d.ts +26 -24
- package/dist/generated/types.gen.d.ts +662 -280
- package/dist/index.js +510 -125
- package/dist/push/index.js +547 -153
- package/package.json +1 -1
package/dist/push/index.js
CHANGED
|
@@ -13135,7 +13135,7 @@ class StepExecutions extends HeyApiClient {
|
|
|
13135
13135
|
class PipelineDefinitions extends HeyApiClient {
|
|
13136
13136
|
createPipelineDefinition(options) {
|
|
13137
13137
|
return (options.client ?? this.client).post({
|
|
13138
|
-
url: "/api/
|
|
13138
|
+
url: "/api/pipeline-definitions",
|
|
13139
13139
|
...options,
|
|
13140
13140
|
headers: {
|
|
13141
13141
|
"Content-Type": "application/json",
|
|
@@ -13145,7 +13145,7 @@ class PipelineDefinitions extends HeyApiClient {
|
|
|
13145
13145
|
}
|
|
13146
13146
|
upsertPipelineDefinition(options) {
|
|
13147
13147
|
return (options.client ?? this.client).put({
|
|
13148
|
-
url: "/api/
|
|
13148
|
+
url: "/api/pipeline-definitions",
|
|
13149
13149
|
...options,
|
|
13150
13150
|
headers: {
|
|
13151
13151
|
"Content-Type": "application/json",
|
|
@@ -13154,14 +13154,14 @@ class PipelineDefinitions extends HeyApiClient {
|
|
|
13154
13154
|
});
|
|
13155
13155
|
}
|
|
13156
13156
|
archivePipelineDefinition(options) {
|
|
13157
|
-
return (options.client ?? this.client).put({ url: "/api/
|
|
13157
|
+
return (options.client ?? this.client).put({ url: "/api/pipeline-definitions/{pipelineDefinitionId}/archive", ...options });
|
|
13158
13158
|
}
|
|
13159
13159
|
unarchivePipelineDefinition(options) {
|
|
13160
|
-
return (options.client ?? this.client).put({ url: "/api/
|
|
13160
|
+
return (options.client ?? this.client).put({ url: "/api/pipeline-definitions/{pipelineDefinitionId}/unarchive", ...options });
|
|
13161
13161
|
}
|
|
13162
13162
|
addPipelineStep(options) {
|
|
13163
13163
|
return (options.client ?? this.client).post({
|
|
13164
|
-
url: "/api/
|
|
13164
|
+
url: "/api/pipeline-definitions/{pipelineDefinitionId}/steps",
|
|
13165
13165
|
...options,
|
|
13166
13166
|
headers: {
|
|
13167
13167
|
"Content-Type": "application/json",
|
|
@@ -13170,11 +13170,11 @@ class PipelineDefinitions extends HeyApiClient {
|
|
|
13170
13170
|
});
|
|
13171
13171
|
}
|
|
13172
13172
|
removePipelineStep(options) {
|
|
13173
|
-
return (options.client ?? this.client).delete({ url: "/api/
|
|
13173
|
+
return (options.client ?? this.client).delete({ url: "/api/pipeline-definitions/{pipelineDefinitionId}/steps/{pipelineStepDefinitionId}", ...options });
|
|
13174
13174
|
}
|
|
13175
13175
|
updatePipelineStep(options) {
|
|
13176
13176
|
return (options.client ?? this.client).put({
|
|
13177
|
-
url: "/api/
|
|
13177
|
+
url: "/api/pipeline-definitions/{pipelineDefinitionId}/steps/{pipelineStepDefinitionId}",
|
|
13178
13178
|
...options,
|
|
13179
13179
|
headers: {
|
|
13180
13180
|
"Content-Type": "application/json",
|
|
@@ -13184,7 +13184,7 @@ class PipelineDefinitions extends HeyApiClient {
|
|
|
13184
13184
|
}
|
|
13185
13185
|
setPipelineStepAdvancementPolicy(options) {
|
|
13186
13186
|
return (options.client ?? this.client).put({
|
|
13187
|
-
url: "/api/
|
|
13187
|
+
url: "/api/pipeline-definitions/{pipelineDefinitionId}/steps/{pipelineStepDefinitionId}/advancement-policy",
|
|
13188
13188
|
...options,
|
|
13189
13189
|
headers: {
|
|
13190
13190
|
"Content-Type": "application/json",
|
|
@@ -13193,20 +13193,20 @@ class PipelineDefinitions extends HeyApiClient {
|
|
|
13193
13193
|
});
|
|
13194
13194
|
}
|
|
13195
13195
|
getPipelineDefinition(options) {
|
|
13196
|
-
return (options.client ?? this.client).get({ url: "/api/
|
|
13196
|
+
return (options.client ?? this.client).get({ url: "/api/pipeline-definitions/{pipelineDefinitionId}", ...options });
|
|
13197
13197
|
}
|
|
13198
13198
|
listPipelineDefinitions(options) {
|
|
13199
|
-
return (options.client ?? this.client).get({ url: "/api/projects/{projectId}/
|
|
13199
|
+
return (options.client ?? this.client).get({ url: "/api/projects/{projectId}/pipeline-definitions", ...options });
|
|
13200
13200
|
}
|
|
13201
13201
|
}
|
|
13202
13202
|
|
|
13203
13203
|
class PipelineExecutions extends HeyApiClient {
|
|
13204
13204
|
listPipelineExecutions(options) {
|
|
13205
|
-
return (options.client ?? this.client).get({ url: "/api/
|
|
13205
|
+
return (options.client ?? this.client).get({ url: "/api/pipeline-executions", ...options });
|
|
13206
13206
|
}
|
|
13207
13207
|
createPipelineExecution(options) {
|
|
13208
13208
|
return (options.client ?? this.client).post({
|
|
13209
|
-
url: "/api/
|
|
13209
|
+
url: "/api/pipeline-executions",
|
|
13210
13210
|
...options,
|
|
13211
13211
|
headers: {
|
|
13212
13212
|
"Content-Type": "application/json",
|
|
@@ -13215,17 +13215,17 @@ class PipelineExecutions extends HeyApiClient {
|
|
|
13215
13215
|
});
|
|
13216
13216
|
}
|
|
13217
13217
|
startPipelineExecution(options) {
|
|
13218
|
-
return (options.client ?? this.client).put({ url: "/api/
|
|
13218
|
+
return (options.client ?? this.client).put({ url: "/api/pipeline-executions/{pipelineExecutionId}/start", ...options });
|
|
13219
13219
|
}
|
|
13220
13220
|
queueFirstPipelineStepRun(options) {
|
|
13221
|
-
return (options.client ?? this.client).post({ url: "/api/
|
|
13221
|
+
return (options.client ?? this.client).post({ url: "/api/pipeline-executions/{pipelineExecutionId}/step-runs/first", ...options });
|
|
13222
13222
|
}
|
|
13223
13223
|
markPipelineStepRunRunning(options) {
|
|
13224
|
-
return (options.client ?? this.client).put({ url: "/api/
|
|
13224
|
+
return (options.client ?? this.client).put({ url: "/api/pipeline-executions/{pipelineExecutionId}/step-runs/{pipelineStepRunId}/running", ...options });
|
|
13225
13225
|
}
|
|
13226
13226
|
applyPipelineStepResult(options) {
|
|
13227
13227
|
return (options.client ?? this.client).post({
|
|
13228
|
-
url: "/api/
|
|
13228
|
+
url: "/api/pipeline-executions/{pipelineExecutionId}/step-runs/{pipelineStepRunId}/results",
|
|
13229
13229
|
...options,
|
|
13230
13230
|
headers: {
|
|
13231
13231
|
"Content-Type": "application/json",
|
|
@@ -13235,7 +13235,17 @@ class PipelineExecutions extends HeyApiClient {
|
|
|
13235
13235
|
}
|
|
13236
13236
|
acceptPipelineStepRun(options) {
|
|
13237
13237
|
return (options.client ?? this.client).post({
|
|
13238
|
-
url: "/api/
|
|
13238
|
+
url: "/api/pipeline-executions/{pipelineExecutionId}/step-runs/{pipelineStepRunId}/accept",
|
|
13239
|
+
...options,
|
|
13240
|
+
headers: {
|
|
13241
|
+
"Content-Type": "application/json",
|
|
13242
|
+
...options.headers
|
|
13243
|
+
}
|
|
13244
|
+
});
|
|
13245
|
+
}
|
|
13246
|
+
acceptPipelineCohort(options) {
|
|
13247
|
+
return (options.client ?? this.client).post({
|
|
13248
|
+
url: "/api/pipeline-executions/{pipelineExecutionId}/cohorts/{originNodeDefinitionId}/accept",
|
|
13239
13249
|
...options,
|
|
13240
13250
|
headers: {
|
|
13241
13251
|
"Content-Type": "application/json",
|
|
@@ -13245,7 +13255,7 @@ class PipelineExecutions extends HeyApiClient {
|
|
|
13245
13255
|
}
|
|
13246
13256
|
rerunPipelineExecution(options) {
|
|
13247
13257
|
return (options.client ?? this.client).post({
|
|
13248
|
-
url: "/api/
|
|
13258
|
+
url: "/api/pipeline-executions/{pipelineExecutionId}/rerun",
|
|
13249
13259
|
...options,
|
|
13250
13260
|
headers: {
|
|
13251
13261
|
"Content-Type": "application/json",
|
|
@@ -13254,19 +13264,22 @@ class PipelineExecutions extends HeyApiClient {
|
|
|
13254
13264
|
});
|
|
13255
13265
|
}
|
|
13256
13266
|
cancelPipelineExecution(options) {
|
|
13257
|
-
return (options.client ?? this.client).put({ url: "/api/
|
|
13267
|
+
return (options.client ?? this.client).put({ url: "/api/pipeline-executions/{pipelineExecutionId}/cancel", ...options });
|
|
13258
13268
|
}
|
|
13259
13269
|
getPipelineExecution(options) {
|
|
13260
|
-
return (options.client ?? this.client).get({ url: "/api/
|
|
13270
|
+
return (options.client ?? this.client).get({ url: "/api/pipeline-executions/{pipelineExecutionId}", ...options });
|
|
13271
|
+
}
|
|
13272
|
+
getPipelineExecutionRoutedChain(options) {
|
|
13273
|
+
return (options.client ?? this.client).get({ url: "/api/pipeline-executions/{pipelineExecutionId}/routed-chain", ...options });
|
|
13261
13274
|
}
|
|
13262
13275
|
countPipelineExecutionsByPipeline(options) {
|
|
13263
|
-
return (options.client ?? this.client).get({ url: "/api/
|
|
13276
|
+
return (options.client ?? this.client).get({ url: "/api/pipeline-executions/counts/by-pipeline", ...options });
|
|
13264
13277
|
}
|
|
13265
13278
|
listPipelineDefinitionStepRollups(options) {
|
|
13266
|
-
return (options.client ?? this.client).get({ url: "/api/
|
|
13279
|
+
return (options.client ?? this.client).get({ url: "/api/pipeline-executions/step-rollups/by-definition/{pipelineDefinitionId}", ...options });
|
|
13267
13280
|
}
|
|
13268
13281
|
listPipelineDefinitionStepRuns(options) {
|
|
13269
|
-
return (options.client ?? this.client).get({ url: "/api/
|
|
13282
|
+
return (options.client ?? this.client).get({ url: "/api/pipeline-executions/step-runs/by-definition/{pipelineDefinitionId}", ...options });
|
|
13270
13283
|
}
|
|
13271
13284
|
}
|
|
13272
13285
|
|
|
@@ -16205,6 +16218,140 @@ function extractInlineComputedSignals(policy) {
|
|
|
16205
16218
|
return [...byKey.values()];
|
|
16206
16219
|
}
|
|
16207
16220
|
|
|
16221
|
+
// src/definitions/advancement-policies/cohort-advancement-policy.ts
|
|
16222
|
+
var cohortAdvancementEventTypeValues = ["continue", "block"];
|
|
16223
|
+
function serializeCohortCondition(condition) {
|
|
16224
|
+
if (condition._tag === "signal") {
|
|
16225
|
+
return {
|
|
16226
|
+
fact: typeof condition.signal === "string" ? condition.signal : condition.signal.key,
|
|
16227
|
+
operator: condition.operator,
|
|
16228
|
+
value: condition.value
|
|
16229
|
+
};
|
|
16230
|
+
}
|
|
16231
|
+
if (condition._tag === "all") {
|
|
16232
|
+
return { all: condition.conditions.map(serializeCohortCondition) };
|
|
16233
|
+
}
|
|
16234
|
+
return { any: condition.conditions.map(serializeCohortCondition) };
|
|
16235
|
+
}
|
|
16236
|
+
function serializeCohortRule(rule) {
|
|
16237
|
+
return {
|
|
16238
|
+
conditions: { [rule.mode]: rule.conditions.map(serializeCohortCondition) },
|
|
16239
|
+
event: {
|
|
16240
|
+
type: rule.outcome,
|
|
16241
|
+
...rule.outcomeJson ? { params: rule.outcomeJson } : {}
|
|
16242
|
+
}
|
|
16243
|
+
};
|
|
16244
|
+
}
|
|
16245
|
+
function serializeCohortAdvancementPolicy(policy) {
|
|
16246
|
+
if (!policy) {
|
|
16247
|
+
return { rules: [], defaultEventType: "continue", defaultEventParamsJson: null };
|
|
16248
|
+
}
|
|
16249
|
+
return {
|
|
16250
|
+
rules: (policy.rules ?? []).map(serializeCohortRule),
|
|
16251
|
+
defaultEventType: policy.default,
|
|
16252
|
+
defaultEventParamsJson: policy.defaultParamsJson ?? null
|
|
16253
|
+
};
|
|
16254
|
+
}
|
|
16255
|
+
function visitCohortSignalConditions(conditions, visit) {
|
|
16256
|
+
for (const c of conditions) {
|
|
16257
|
+
if (c._tag === "signal") {
|
|
16258
|
+
visit(c);
|
|
16259
|
+
} else {
|
|
16260
|
+
visitCohortSignalConditions(c.conditions, visit);
|
|
16261
|
+
}
|
|
16262
|
+
}
|
|
16263
|
+
}
|
|
16264
|
+
function isSameStepSignalsListDefinition(a, b) {
|
|
16265
|
+
return JSON.stringify(a.ops) === JSON.stringify(b.ops) && JSON.stringify(a.reducer) === JSON.stringify(b.reducer);
|
|
16266
|
+
}
|
|
16267
|
+
function extractInlineStepSignalsListDefinitions(policy) {
|
|
16268
|
+
if (!policy?.rules)
|
|
16269
|
+
return [];
|
|
16270
|
+
const byKey = new Map;
|
|
16271
|
+
for (const rule of policy.rules) {
|
|
16272
|
+
visitCohortSignalConditions(rule.conditions, (cond) => {
|
|
16273
|
+
if (typeof cond.signal === "string")
|
|
16274
|
+
return;
|
|
16275
|
+
const inline = cond.signal;
|
|
16276
|
+
const def = {
|
|
16277
|
+
key: inline.key,
|
|
16278
|
+
ops: inline.ops,
|
|
16279
|
+
reducer: inline.reducer
|
|
16280
|
+
};
|
|
16281
|
+
const existing = byKey.get(def.key);
|
|
16282
|
+
if (existing) {
|
|
16283
|
+
if (!isSameStepSignalsListDefinition(existing, def)) {
|
|
16284
|
+
throw new Error(`Conflicting inline stepSignalsList definitions for key "${def.key}"`);
|
|
16285
|
+
}
|
|
16286
|
+
return;
|
|
16287
|
+
}
|
|
16288
|
+
byKey.set(def.key, def);
|
|
16289
|
+
});
|
|
16290
|
+
}
|
|
16291
|
+
return [...byKey.values()];
|
|
16292
|
+
}
|
|
16293
|
+
|
|
16294
|
+
// src/definitions/pipelines/chain-graph.ts
|
|
16295
|
+
function tryOrderChainNodeDefinitions(nodeDefinitions, dependencyEdges) {
|
|
16296
|
+
const nodesByKey = new Map;
|
|
16297
|
+
for (const nodeDefinition of nodeDefinitions) {
|
|
16298
|
+
nodesByKey.set(nodeDefinition.nodeKey, nodeDefinition);
|
|
16299
|
+
}
|
|
16300
|
+
const outgoing = new Map;
|
|
16301
|
+
const incomingCount = new Map;
|
|
16302
|
+
for (const nodeDefinition of nodeDefinitions) {
|
|
16303
|
+
incomingCount.set(nodeDefinition.nodeKey, 0);
|
|
16304
|
+
}
|
|
16305
|
+
for (const edge of dependencyEdges) {
|
|
16306
|
+
if (!nodesByKey.has(edge.fromNodeKey) || !nodesByKey.has(edge.toNodeKey)) {
|
|
16307
|
+
return null;
|
|
16308
|
+
}
|
|
16309
|
+
if (outgoing.has(edge.fromNodeKey))
|
|
16310
|
+
return null;
|
|
16311
|
+
outgoing.set(edge.fromNodeKey, edge.toNodeKey);
|
|
16312
|
+
incomingCount.set(edge.toNodeKey, (incomingCount.get(edge.toNodeKey) ?? 0) + 1);
|
|
16313
|
+
}
|
|
16314
|
+
for (const count of incomingCount.values()) {
|
|
16315
|
+
if (count > 1)
|
|
16316
|
+
return null;
|
|
16317
|
+
}
|
|
16318
|
+
if (nodeDefinitions.length === 0)
|
|
16319
|
+
return [];
|
|
16320
|
+
const roots = nodeDefinitions.filter((nodeDefinition) => (incomingCount.get(nodeDefinition.nodeKey) ?? 0) === 0);
|
|
16321
|
+
if (roots.length !== 1)
|
|
16322
|
+
return null;
|
|
16323
|
+
const rootNode = roots[0];
|
|
16324
|
+
if (!rootNode)
|
|
16325
|
+
return null;
|
|
16326
|
+
const ordered = [];
|
|
16327
|
+
const visited = new Set;
|
|
16328
|
+
let currentKey = rootNode.nodeKey;
|
|
16329
|
+
while (currentKey !== undefined) {
|
|
16330
|
+
if (visited.has(currentKey))
|
|
16331
|
+
return null;
|
|
16332
|
+
visited.add(currentKey);
|
|
16333
|
+
const currentNode = nodesByKey.get(currentKey);
|
|
16334
|
+
if (!currentNode)
|
|
16335
|
+
return null;
|
|
16336
|
+
ordered.push(currentNode);
|
|
16337
|
+
currentKey = outgoing.get(currentKey);
|
|
16338
|
+
}
|
|
16339
|
+
if (ordered.length !== nodeDefinitions.length)
|
|
16340
|
+
return null;
|
|
16341
|
+
return ordered;
|
|
16342
|
+
}
|
|
16343
|
+
function buildChainDependencyEdges(orderedNodes) {
|
|
16344
|
+
const dependencyEdges = [];
|
|
16345
|
+
for (let index = 0;index < orderedNodes.length - 1; index += 1) {
|
|
16346
|
+
const from = orderedNodes[index];
|
|
16347
|
+
const to = orderedNodes[index + 1];
|
|
16348
|
+
if (!from || !to)
|
|
16349
|
+
continue;
|
|
16350
|
+
dependencyEdges.push({ fromNodeKey: from.nodeKey, toNodeKey: to.nodeKey });
|
|
16351
|
+
}
|
|
16352
|
+
return dependencyEdges;
|
|
16353
|
+
}
|
|
16354
|
+
|
|
16208
16355
|
// src/definitions/pipelines/define-pipeline.ts
|
|
16209
16356
|
function serializeBinding(binding) {
|
|
16210
16357
|
if (binding.source === "pipeline_input") {
|
|
@@ -16223,15 +16370,42 @@ function serializeBinding(binding) {
|
|
|
16223
16370
|
if (binding.source === "literal") {
|
|
16224
16371
|
return { source: "literal", value: binding.value };
|
|
16225
16372
|
}
|
|
16373
|
+
if (binding.source === "signals_list") {
|
|
16374
|
+
return { source: "signals_list", stepKey: binding.fanOutStep.key };
|
|
16375
|
+
}
|
|
16376
|
+
if (binding.source === "fan_out_item") {
|
|
16377
|
+
return { source: "fan_out_item" };
|
|
16378
|
+
}
|
|
16226
16379
|
return { source: "step_output", stepKey: binding.step.key };
|
|
16227
16380
|
}
|
|
16381
|
+
var isFanOutConfig = (node) => ("nodeType" in node) && node.nodeType === "fanOut";
|
|
16382
|
+
var isCohortGateConfig = (node) => ("nodeType" in node) && node.nodeType === "cohortGate";
|
|
16383
|
+
function serializeInputBindings(input, pipelineInputBindings) {
|
|
16384
|
+
const autoBindings = {
|
|
16385
|
+
workItemTitle: { source: "work_item", field: "title" },
|
|
16386
|
+
workItemDescription: { source: "work_item", field: "description" }
|
|
16387
|
+
};
|
|
16388
|
+
const pipelineBindings = {};
|
|
16389
|
+
for (const [key, binding] of Object.entries(pipelineInputBindings ?? {})) {
|
|
16390
|
+
pipelineBindings[key] = serializeBinding(binding);
|
|
16391
|
+
}
|
|
16392
|
+
const explicitBindings = Object.fromEntries(Object.entries(input ?? {}).filter((entry) => entry[1] !== undefined).map(([key, binding]) => [key, serializeBinding(binding)]));
|
|
16393
|
+
return { ...autoBindings, ...pipelineBindings, ...explicitBindings };
|
|
16394
|
+
}
|
|
16228
16395
|
function buildPipelineSpec(config2) {
|
|
16229
|
-
const
|
|
16396
|
+
const nodes = config2.nodes;
|
|
16230
16397
|
const stepDefMap = new Map;
|
|
16231
|
-
|
|
16232
|
-
const mapKey = `${
|
|
16398
|
+
const registerStepDef = (step) => {
|
|
16399
|
+
const mapKey = `${step.key}@v${String(step.version)}`;
|
|
16233
16400
|
if (!stepDefMap.has(mapKey)) {
|
|
16234
|
-
stepDefMap.set(mapKey,
|
|
16401
|
+
stepDefMap.set(mapKey, step);
|
|
16402
|
+
}
|
|
16403
|
+
};
|
|
16404
|
+
for (const node of nodes) {
|
|
16405
|
+
if (isFanOutConfig(node)) {
|
|
16406
|
+
registerStepDef(node.fanOutStep);
|
|
16407
|
+
} else if (!isCohortGateConfig(node)) {
|
|
16408
|
+
registerStepDef(node.step);
|
|
16235
16409
|
}
|
|
16236
16410
|
}
|
|
16237
16411
|
let inputSchemaJson = null;
|
|
@@ -16242,6 +16416,46 @@ function buildPipelineSpec(config2) {
|
|
|
16242
16416
|
inputSchemaJson = null;
|
|
16243
16417
|
}
|
|
16244
16418
|
}
|
|
16419
|
+
const nodeDefinitions = nodes.map((node) => {
|
|
16420
|
+
if (isCohortGateConfig(node)) {
|
|
16421
|
+
const serializedPolicy = serializeCohortAdvancementPolicy(node.advanceAll);
|
|
16422
|
+
const inlineStepSignalsListDefinitions = extractInlineStepSignalsListDefinitions(node.advanceAll);
|
|
16423
|
+
return {
|
|
16424
|
+
nodeKey: node.nodeKey,
|
|
16425
|
+
kind: "cohortGate",
|
|
16426
|
+
advanceAllPolicyDefinition: serializedPolicy,
|
|
16427
|
+
stepSignalsListDefinitions: [
|
|
16428
|
+
...inlineStepSignalsListDefinitions,
|
|
16429
|
+
...node.stepSignalsListDefinitions ?? []
|
|
16430
|
+
]
|
|
16431
|
+
};
|
|
16432
|
+
}
|
|
16433
|
+
if (isFanOutConfig(node)) {
|
|
16434
|
+
return {
|
|
16435
|
+
nodeKey: node.fanOutStep.key,
|
|
16436
|
+
kind: "fanOut",
|
|
16437
|
+
stepKey: node.fanOutStep.key,
|
|
16438
|
+
stepName: node.fanOutStep.name,
|
|
16439
|
+
stepDescription: node.fanOutStep.description,
|
|
16440
|
+
inputBindingsJson: serializeInputBindings(node.input, config2.pipelineInputBindings),
|
|
16441
|
+
timeoutSeconds: node.timeout ?? null,
|
|
16442
|
+
overSignalKey: node.overSignalKey,
|
|
16443
|
+
advanceEachPolicyDefinition: serializeCohortAdvancementPolicy(node.advanceEach)
|
|
16444
|
+
};
|
|
16445
|
+
}
|
|
16446
|
+
return {
|
|
16447
|
+
nodeKey: node.step.key,
|
|
16448
|
+
kind: "step",
|
|
16449
|
+
stepKey: node.step.key,
|
|
16450
|
+
stepName: node.step.name,
|
|
16451
|
+
stepDescription: node.step.description,
|
|
16452
|
+
inputBindingsJson: serializeInputBindings(node.input, config2.pipelineInputBindings),
|
|
16453
|
+
timeoutSeconds: node.timeout ?? null,
|
|
16454
|
+
advancementPolicyDefinition: serializeAdvancementPolicy(node.advancement),
|
|
16455
|
+
computedSignalDefinitions: extractInlineComputedSignals(node.advancement)
|
|
16456
|
+
};
|
|
16457
|
+
});
|
|
16458
|
+
const dependencyEdges = buildChainDependencyEdges(nodeDefinitions);
|
|
16245
16459
|
return {
|
|
16246
16460
|
key: config2.key,
|
|
16247
16461
|
name: config2.name,
|
|
@@ -16250,31 +16464,8 @@ function buildPipelineSpec(config2) {
|
|
|
16250
16464
|
status: config2.status ?? "active",
|
|
16251
16465
|
inputSchemaJson,
|
|
16252
16466
|
_stepDefinitions: [...stepDefMap.values()],
|
|
16253
|
-
|
|
16254
|
-
|
|
16255
|
-
workItemTitle: { source: "work_item", field: "title" },
|
|
16256
|
-
workItemDescription: { source: "work_item", field: "description" }
|
|
16257
|
-
};
|
|
16258
|
-
const pipelineBindings = {};
|
|
16259
|
-
for (const [key, binding] of Object.entries(config2.pipelineInputBindings ?? {})) {
|
|
16260
|
-
pipelineBindings[key] = serializeBinding(binding);
|
|
16261
|
-
}
|
|
16262
|
-
const explicitStepBindings = Object.fromEntries(Object.entries(stepConfig.input ?? {}).filter((entry) => entry[1] !== undefined).map(([key, binding]) => [key, serializeBinding(binding)]));
|
|
16263
|
-
return {
|
|
16264
|
-
stepKey: stepConfig.step.key,
|
|
16265
|
-
stepName: stepConfig.step.name,
|
|
16266
|
-
stepDescription: stepConfig.step.description,
|
|
16267
|
-
position: index + 1,
|
|
16268
|
-
inputBindingsJson: {
|
|
16269
|
-
...autoBindings,
|
|
16270
|
-
...pipelineBindings,
|
|
16271
|
-
...explicitStepBindings
|
|
16272
|
-
},
|
|
16273
|
-
timeoutSeconds: stepConfig.timeout ?? null,
|
|
16274
|
-
advancementPolicyDefinition: serializeAdvancementPolicy(stepConfig.advancement),
|
|
16275
|
-
computedSignalDefinitions: extractInlineComputedSignals(stepConfig.advancement)
|
|
16276
|
-
};
|
|
16277
|
-
})
|
|
16467
|
+
nodeDefinitions,
|
|
16468
|
+
dependencyEdges
|
|
16278
16469
|
};
|
|
16279
16470
|
}
|
|
16280
16471
|
// src/definitions/advancement-policies/fluent-rules.ts
|
|
@@ -16445,7 +16636,10 @@ function makeStepInputCtx(inputSchema) {
|
|
|
16445
16636
|
output(step) {
|
|
16446
16637
|
return { source: "step_output", step };
|
|
16447
16638
|
},
|
|
16448
|
-
literal: literal2
|
|
16639
|
+
literal: literal2,
|
|
16640
|
+
signalsList(fanOutStep) {
|
|
16641
|
+
return { source: "signals_list", fanOutStep };
|
|
16642
|
+
}
|
|
16449
16643
|
};
|
|
16450
16644
|
}
|
|
16451
16645
|
function literal2(value) {
|
|
@@ -16490,61 +16684,247 @@ function mergeStepBindings(pipelineBindings, explicitBindings) {
|
|
|
16490
16684
|
return Object.keys(merged).length > 0 ? merged : undefined;
|
|
16491
16685
|
}
|
|
16492
16686
|
|
|
16493
|
-
// src/definitions/
|
|
16494
|
-
|
|
16495
|
-
|
|
16496
|
-
|
|
16497
|
-
|
|
16498
|
-
|
|
16499
|
-
|
|
16500
|
-
|
|
16501
|
-
|
|
16502
|
-
|
|
16503
|
-
this.steps = steps;
|
|
16504
|
-
this.pipelineInputBindings = pipelineInputBindings;
|
|
16505
|
-
this.pipelineStepInputBindings = pipelineStepInputBindings;
|
|
16506
|
-
}
|
|
16507
|
-
advance(callback) {
|
|
16508
|
-
const last = this.steps.at(-1);
|
|
16509
|
-
if (!last)
|
|
16510
|
-
throw new Error("Internal error: no steps available");
|
|
16511
|
-
const ctx = makeAdvanceCtx();
|
|
16512
|
-
const result = callback(ctx);
|
|
16513
|
-
const policy = {
|
|
16514
|
-
defaultOutcome: result.default,
|
|
16515
|
-
...result.rules !== undefined ? { rules: result.rules } : {}
|
|
16687
|
+
// src/definitions/advancement-policies/cohort-fluent-rules.ts
|
|
16688
|
+
var LEAF_BRAND2 = Symbol("boboddy.cohortRule.leaf");
|
|
16689
|
+
var GROUP_BRAND2 = Symbol("boboddy.cohortRule.group");
|
|
16690
|
+
function createCohortSignalRef(signal2) {
|
|
16691
|
+
const leaf = (operator, value) => {
|
|
16692
|
+
const condition = {
|
|
16693
|
+
_tag: "signal",
|
|
16694
|
+
signal: signal2,
|
|
16695
|
+
operator,
|
|
16696
|
+
value
|
|
16516
16697
|
};
|
|
16517
|
-
|
|
16518
|
-
|
|
16519
|
-
|
|
16698
|
+
return {
|
|
16699
|
+
[LEAF_BRAND2]: condition,
|
|
16700
|
+
then(outcome, paramsJson) {
|
|
16701
|
+
return {
|
|
16702
|
+
_tag: "rule",
|
|
16703
|
+
mode: "all",
|
|
16704
|
+
conditions: [condition],
|
|
16705
|
+
outcome,
|
|
16706
|
+
...paramsJson ? { outcomeJson: paramsJson } : {}
|
|
16707
|
+
};
|
|
16708
|
+
}
|
|
16709
|
+
};
|
|
16710
|
+
};
|
|
16711
|
+
return {
|
|
16712
|
+
eq: (v) => leaf("equal", v),
|
|
16713
|
+
ne: (v) => leaf("notEqual", v),
|
|
16714
|
+
gt: (v) => leaf("greaterThan", v),
|
|
16715
|
+
gte: (v) => leaf("greaterThanInclusive", v),
|
|
16716
|
+
lt: (v) => leaf("lessThan", v),
|
|
16717
|
+
lte: (v) => leaf("lessThanInclusive", v),
|
|
16718
|
+
in: (vs) => leaf("in", vs),
|
|
16719
|
+
notIn: (vs) => leaf("notIn", vs),
|
|
16720
|
+
contains: (v) => leaf("contains", v),
|
|
16721
|
+
doesNotContain: (v) => leaf("doesNotContain", v)
|
|
16722
|
+
};
|
|
16723
|
+
}
|
|
16724
|
+
function createCohortLeafFromCondition(condition) {
|
|
16725
|
+
return {
|
|
16726
|
+
[LEAF_BRAND2]: condition,
|
|
16727
|
+
then(outcome, paramsJson) {
|
|
16728
|
+
return {
|
|
16729
|
+
_tag: "rule",
|
|
16730
|
+
mode: "all",
|
|
16731
|
+
conditions: [condition],
|
|
16732
|
+
outcome,
|
|
16733
|
+
...paramsJson ? { outcomeJson: paramsJson } : {}
|
|
16734
|
+
};
|
|
16735
|
+
}
|
|
16736
|
+
};
|
|
16737
|
+
}
|
|
16738
|
+
function extractCohortCondition(ref) {
|
|
16739
|
+
if (LEAF_BRAND2 in ref)
|
|
16740
|
+
return ref[LEAF_BRAND2];
|
|
16741
|
+
const group = ref[GROUP_BRAND2];
|
|
16742
|
+
return group.mode === "all" ? { _tag: "all", conditions: group.conditions } : { _tag: "any", conditions: group.conditions };
|
|
16743
|
+
}
|
|
16744
|
+
function createCohortGroup(mode, refs) {
|
|
16745
|
+
const conditions = refs.map(extractCohortCondition);
|
|
16746
|
+
return {
|
|
16747
|
+
[GROUP_BRAND2]: { mode, conditions },
|
|
16748
|
+
then(outcome, paramsJson) {
|
|
16749
|
+
return {
|
|
16750
|
+
_tag: "rule",
|
|
16751
|
+
mode,
|
|
16752
|
+
conditions,
|
|
16753
|
+
outcome,
|
|
16754
|
+
...paramsJson ? { outcomeJson: paramsJson } : {}
|
|
16755
|
+
};
|
|
16756
|
+
}
|
|
16757
|
+
};
|
|
16758
|
+
}
|
|
16759
|
+
function makeKeyedCohortSignalRef(key) {
|
|
16760
|
+
return createCohortSignalRef(key);
|
|
16761
|
+
}
|
|
16762
|
+
function makeAdvanceEachCtx() {
|
|
16763
|
+
return {
|
|
16764
|
+
signal: (key) => makeKeyedCohortSignalRef(key),
|
|
16765
|
+
stepSignals: new Proxy({}, {
|
|
16766
|
+
get(_, key) {
|
|
16767
|
+
if (typeof key === "string")
|
|
16768
|
+
return makeKeyedCohortSignalRef(key);
|
|
16769
|
+
return;
|
|
16770
|
+
}
|
|
16771
|
+
}),
|
|
16772
|
+
all: (...refs) => createCohortGroup("all", refs),
|
|
16773
|
+
any: (...refs) => createCohortGroup("any", refs)
|
|
16774
|
+
};
|
|
16775
|
+
}
|
|
16776
|
+
var branchOutcomeValues = [
|
|
16777
|
+
"continue",
|
|
16778
|
+
"block",
|
|
16779
|
+
"error",
|
|
16780
|
+
"abandoned"
|
|
16781
|
+
];
|
|
16782
|
+
function summarizeTransformOp(op) {
|
|
16783
|
+
if (op.op === "filter") {
|
|
16784
|
+
return `filter_${op.operator}_${JSON.stringify(op.value)}`;
|
|
16785
|
+
}
|
|
16786
|
+
if (op.op === "sortBy") {
|
|
16787
|
+
return `sortBy_${op.direction}`;
|
|
16788
|
+
}
|
|
16789
|
+
return "unique";
|
|
16790
|
+
}
|
|
16791
|
+
function deriveStepSignalsListKey(ops, reducer) {
|
|
16792
|
+
const pluck = ops.find((op) => op.op === "pluck");
|
|
16793
|
+
const base = `${reducer.op}_${pluck?.signalKey ?? "value"}`;
|
|
16794
|
+
const extras = ops.filter((op) => op.op !== "pluck").map(summarizeTransformOp);
|
|
16795
|
+
const reducerExtra = reducer.op === "join" ? `sep_${reducer.separator}` : null;
|
|
16796
|
+
const suffixParts = [...extras, ...reducerExtra ? [reducerExtra] : []];
|
|
16797
|
+
return suffixParts.length > 0 ? `${base}_${suffixParts.join("_")}` : base;
|
|
16798
|
+
}
|
|
16799
|
+
function createStepSignalsListBuilder(ops) {
|
|
16800
|
+
const withOp = (op) => createStepSignalsListBuilder([...ops, op]);
|
|
16801
|
+
const reduce = (reducer) => {
|
|
16802
|
+
const token = {
|
|
16803
|
+
_tag: "step_signals_list",
|
|
16804
|
+
key: deriveStepSignalsListKey(ops, reducer),
|
|
16805
|
+
ops: [...ops],
|
|
16806
|
+
reducer
|
|
16807
|
+
};
|
|
16808
|
+
return createCohortSignalRef(token);
|
|
16809
|
+
};
|
|
16810
|
+
return {
|
|
16811
|
+
filter: (operator, value) => withOp({ op: "filter", operator, value }),
|
|
16812
|
+
sortBy: (direction = "asc") => withOp({ op: "sortBy", direction }),
|
|
16813
|
+
unique: () => withOp({ op: "unique" }),
|
|
16814
|
+
count: () => reduce({ op: "count" }),
|
|
16815
|
+
sum: () => reduce({ op: "sum" }),
|
|
16816
|
+
avg: () => reduce({ op: "avg" }),
|
|
16817
|
+
min: () => reduce({ op: "min" }),
|
|
16818
|
+
max: () => reduce({ op: "max" }),
|
|
16819
|
+
booleanAll: () => reduce({ op: "booleanAll" }),
|
|
16820
|
+
booleanAny: () => reduce({ op: "booleanAny" }),
|
|
16821
|
+
join: (separator = ",") => reduce({ op: "join", separator }),
|
|
16822
|
+
first: () => reduce({ op: "first" }),
|
|
16823
|
+
last: () => reduce({ op: "last" })
|
|
16824
|
+
};
|
|
16825
|
+
}
|
|
16826
|
+
function makeAdvanceAllCtx() {
|
|
16827
|
+
return {
|
|
16828
|
+
branchOutcomes: {
|
|
16829
|
+
total: () => createCohortSignalRef("branchCount"),
|
|
16830
|
+
count: (outcome) => createCohortSignalRef(`${outcome}Count`),
|
|
16831
|
+
every: (outcome) => createCohortLeafFromCondition({
|
|
16832
|
+
_tag: "signal",
|
|
16833
|
+
signal: `${outcome}Count`,
|
|
16834
|
+
operator: "equal",
|
|
16835
|
+
value: { fact: "branchCount" }
|
|
16836
|
+
}),
|
|
16837
|
+
some: (outcome) => createCohortLeafFromCondition({
|
|
16838
|
+
_tag: "signal",
|
|
16839
|
+
signal: `${outcome}Count`,
|
|
16840
|
+
operator: "greaterThan",
|
|
16841
|
+
value: 0
|
|
16842
|
+
})
|
|
16843
|
+
},
|
|
16844
|
+
stepSignalsList: {
|
|
16845
|
+
pluck: (signalKey) => createStepSignalsListBuilder([{ op: "pluck", signalKey }])
|
|
16846
|
+
},
|
|
16847
|
+
all: (...refs) => createCohortGroup("all", refs),
|
|
16848
|
+
any: (...refs) => createCohortGroup("any", refs)
|
|
16849
|
+
};
|
|
16850
|
+
}
|
|
16851
|
+
|
|
16852
|
+
// src/definitions/pipelines/fan-out-builder.ts
|
|
16853
|
+
function beginFanOut(inputSchema, meta3, nodes, pipelineInputBindings, pipelineStepInputBindings, step, config2) {
|
|
16854
|
+
const baseCtx = makeStepInputCtx(inputSchema);
|
|
16855
|
+
const ctx = {
|
|
16856
|
+
...baseCtx,
|
|
16857
|
+
item: { source: "fan_out_item" }
|
|
16858
|
+
};
|
|
16859
|
+
const rawInput = config2.input ? config2.input(ctx) : {};
|
|
16860
|
+
const input = mergeStepBindings(pipelineStepInputBindings, normalizeInputMapping(rawInput));
|
|
16861
|
+
const fanOutNodeConfig = {
|
|
16862
|
+
nodeType: "fanOut",
|
|
16863
|
+
fanOutStep: step,
|
|
16864
|
+
overSignalKey: config2.over,
|
|
16865
|
+
...input ? { input } : {},
|
|
16866
|
+
...config2.timeout !== undefined ? { timeout: config2.timeout } : {}
|
|
16867
|
+
};
|
|
16868
|
+
const advanceEachCtx = makeAdvanceEachCtx();
|
|
16869
|
+
const advanceEachResult = config2.advance(advanceEachCtx);
|
|
16870
|
+
const advanceEachPolicy = {
|
|
16871
|
+
default: advanceEachResult.default,
|
|
16872
|
+
...advanceEachResult.rules !== undefined ? { rules: advanceEachResult.rules } : {}
|
|
16873
|
+
};
|
|
16874
|
+
fanOutNodeConfig.advanceEach = advanceEachPolicy;
|
|
16875
|
+
const cohortGateNodeConfig = {
|
|
16876
|
+
nodeType: "cohortGate",
|
|
16877
|
+
nodeKey: `${step.key}__cohortGate`
|
|
16878
|
+
};
|
|
16879
|
+
const advanceAllCtx = makeAdvanceAllCtx();
|
|
16880
|
+
const advanceAllResult = config2.advanceAll(advanceAllCtx);
|
|
16881
|
+
const advanceAllPolicy = {
|
|
16882
|
+
default: advanceAllResult.default,
|
|
16883
|
+
...advanceAllResult.rules !== undefined ? { rules: advanceAllResult.rules } : {}
|
|
16884
|
+
};
|
|
16885
|
+
cohortGateNodeConfig.advanceAll = advanceAllPolicy;
|
|
16886
|
+
nodes.push(fanOutNodeConfig, cohortGateNodeConfig);
|
|
16887
|
+
return new PipelineStepBuilder(inputSchema, meta3, nodes, pipelineInputBindings, pipelineStepInputBindings);
|
|
16888
|
+
}
|
|
16889
|
+
|
|
16890
|
+
// src/definitions/pipelines/builder.ts
|
|
16891
|
+
function pushStep(inputSchema, meta3, nodes, pipelineInputBindings, pipelineStepInputBindings, step, rawOptions) {
|
|
16892
|
+
const options = rawOptions;
|
|
16893
|
+
const ctx = makeStepInputCtx(inputSchema);
|
|
16894
|
+
const rawInput = options.input ? options.input(ctx) : {};
|
|
16895
|
+
const input = mergeStepBindings(pipelineStepInputBindings, normalizeInputMapping(rawInput));
|
|
16896
|
+
const stepConfig = { step, input };
|
|
16897
|
+
if (options.timeout !== undefined)
|
|
16898
|
+
stepConfig.timeout = options.timeout;
|
|
16899
|
+
const advanceCtx = makeAdvanceCtx();
|
|
16900
|
+
const result = options.advance(advanceCtx);
|
|
16901
|
+
const policy = {
|
|
16902
|
+
defaultOutcome: result.default,
|
|
16903
|
+
...result.rules !== undefined ? { rules: result.rules } : {}
|
|
16904
|
+
};
|
|
16905
|
+
stepConfig.advancement = policy;
|
|
16906
|
+
nodes.push(stepConfig);
|
|
16907
|
+
return new PipelineStepBuilder(inputSchema, meta3, nodes, pipelineInputBindings, pipelineStepInputBindings);
|
|
16520
16908
|
}
|
|
16521
16909
|
|
|
16522
16910
|
class PipelineStepBuilder {
|
|
16523
16911
|
inputSchema;
|
|
16524
16912
|
meta;
|
|
16525
|
-
|
|
16913
|
+
nodes;
|
|
16526
16914
|
pipelineInputBindings;
|
|
16527
16915
|
pipelineStepInputBindings;
|
|
16528
|
-
constructor(inputSchema, meta3,
|
|
16916
|
+
constructor(inputSchema, meta3, nodes, pipelineInputBindings = {}, pipelineStepInputBindings = {}) {
|
|
16529
16917
|
this.inputSchema = inputSchema;
|
|
16530
16918
|
this.meta = meta3;
|
|
16531
|
-
this.
|
|
16919
|
+
this.nodes = nodes;
|
|
16532
16920
|
this.pipelineInputBindings = pipelineInputBindings;
|
|
16533
16921
|
this.pipelineStepInputBindings = pipelineStepInputBindings;
|
|
16534
16922
|
}
|
|
16535
|
-
step(step,
|
|
16536
|
-
|
|
16537
|
-
|
|
16538
|
-
|
|
16539
|
-
|
|
16540
|
-
if (configFn) {
|
|
16541
|
-
const cfg = {};
|
|
16542
|
-
configFn(cfg);
|
|
16543
|
-
if (cfg.timeout !== undefined)
|
|
16544
|
-
stepConfig.timeout = cfg.timeout;
|
|
16545
|
-
}
|
|
16546
|
-
this.steps.push(stepConfig);
|
|
16547
|
-
return new PipelineStepAdvancementBuilder(this.inputSchema, this.meta, this.steps, this.pipelineInputBindings, this.pipelineStepInputBindings);
|
|
16923
|
+
step(step, options) {
|
|
16924
|
+
return pushStep(this.inputSchema, this.meta, this.nodes, this.pipelineInputBindings, this.pipelineStepInputBindings, step, options);
|
|
16925
|
+
}
|
|
16926
|
+
fanOutStep(step, config2) {
|
|
16927
|
+
return beginFanOut(this.inputSchema, this.meta, this.nodes, this.pipelineInputBindings, this.pipelineStepInputBindings, step, config2);
|
|
16548
16928
|
}
|
|
16549
16929
|
build() {
|
|
16550
16930
|
const config2 = {
|
|
@@ -16554,7 +16934,7 @@ class PipelineStepBuilder {
|
|
|
16554
16934
|
version: this.meta.version,
|
|
16555
16935
|
status: this.meta.status,
|
|
16556
16936
|
input: this.inputSchema,
|
|
16557
|
-
|
|
16937
|
+
nodes: this.nodes,
|
|
16558
16938
|
pipelineInputBindings: this.pipelineInputBindings
|
|
16559
16939
|
};
|
|
16560
16940
|
return buildPipelineSpec(config2);
|
|
@@ -16564,7 +16944,7 @@ class PipelineStepBuilder {
|
|
|
16564
16944
|
class PipelineBuilder {
|
|
16565
16945
|
inputSchema;
|
|
16566
16946
|
meta;
|
|
16567
|
-
|
|
16947
|
+
nodes = [];
|
|
16568
16948
|
pipelineInputBindings;
|
|
16569
16949
|
pipelineStepInputBindings;
|
|
16570
16950
|
constructor(meta3) {
|
|
@@ -16589,19 +16969,8 @@ class PipelineBuilder {
|
|
|
16589
16969
|
}
|
|
16590
16970
|
this.pipelineStepInputBindings = resolveAdditionalStepInputBindings("additionalStepInput", additionalStepInput);
|
|
16591
16971
|
}
|
|
16592
|
-
step(step,
|
|
16593
|
-
|
|
16594
|
-
const rawInput = mapper ? mapper(ctx) : {};
|
|
16595
|
-
const input = mergeStepBindings(this.pipelineStepInputBindings, normalizeInputMapping(rawInput));
|
|
16596
|
-
const stepConfig = { step, input };
|
|
16597
|
-
if (configFn) {
|
|
16598
|
-
const cfg = {};
|
|
16599
|
-
configFn(cfg);
|
|
16600
|
-
if (cfg.timeout !== undefined)
|
|
16601
|
-
stepConfig.timeout = cfg.timeout;
|
|
16602
|
-
}
|
|
16603
|
-
this.steps.push(stepConfig);
|
|
16604
|
-
return new PipelineStepAdvancementBuilder(this.inputSchema, this.meta, this.steps, this.pipelineInputBindings, this.pipelineStepInputBindings);
|
|
16972
|
+
step(step, options) {
|
|
16973
|
+
return pushStep(this.inputSchema, this.meta, this.nodes, this.pipelineInputBindings, this.pipelineStepInputBindings, step, options);
|
|
16605
16974
|
}
|
|
16606
16975
|
}
|
|
16607
16976
|
function pipeline(meta3) {
|
|
@@ -16631,23 +17000,35 @@ var buildPipelineDefinitionsClient = (pipelineDefinitions) => {
|
|
|
16631
17000
|
stepDefMap.set(s.key, s);
|
|
16632
17001
|
}
|
|
16633
17002
|
}
|
|
16634
|
-
const
|
|
16635
|
-
|
|
17003
|
+
const nonStepNode = spec.nodeDefinitions.find((node) => node.kind !== "step");
|
|
17004
|
+
if (nonStepNode) {
|
|
17005
|
+
throw new Error(`Pipeline "${spec.key}" contains a "${nonStepNode.kind}" node ("${nonStepNode.nodeKey}"), ` + `but fan-out pipelines cannot be pushed via the current wire contract yet. ` + `Only "step"-only (chain) pipelines can be pushed with \`upsertFromSpec\` today.`);
|
|
17006
|
+
}
|
|
17007
|
+
const ordered = tryOrderChainNodeDefinitions(spec.nodeDefinitions, spec.dependencyEdges);
|
|
17008
|
+
if (ordered === null) {
|
|
17009
|
+
throw new Error(`Pipeline "${spec.key}" has a malformed step graph: its node and ` + `dependency-edge definitions do not form a single connected, ` + `acyclic chain. This should not happen from the \`pipeline()\` ` + `builder \u2014 check for hand-edited or generated pipeline specs.`);
|
|
17010
|
+
}
|
|
17011
|
+
const stepDefinitions = ordered.map((node, index) => {
|
|
17012
|
+
const stepKey = node.stepKey;
|
|
17013
|
+
if (!stepKey) {
|
|
17014
|
+
throw new Error(`Node "${node.nodeKey}" in pipeline "${spec.key}" has no stepKey.`);
|
|
17015
|
+
}
|
|
17016
|
+
const stepDef = stepDefMap.get(stepKey);
|
|
16636
17017
|
if (!stepDef) {
|
|
16637
|
-
throw new Error(`Step "${
|
|
17018
|
+
throw new Error(`Step "${stepKey}" referenced in pipeline "${spec.key}" was not found on the server. ` + `Run \`boboddy steps push\` first to push your step definitions.`);
|
|
16638
17019
|
}
|
|
16639
17020
|
return {
|
|
16640
17021
|
stepDefinitionId: stepDef.id,
|
|
16641
17022
|
stepDefinitionVersion: stepDef.version,
|
|
16642
|
-
key:
|
|
16643
|
-
name:
|
|
16644
|
-
description:
|
|
16645
|
-
position:
|
|
16646
|
-
inputBindingsJson:
|
|
16647
|
-
timeoutSeconds:
|
|
17023
|
+
key: node.nodeKey,
|
|
17024
|
+
name: node.stepName ?? "",
|
|
17025
|
+
description: node.stepDescription ?? null,
|
|
17026
|
+
position: index + 1,
|
|
17027
|
+
inputBindingsJson: node.inputBindingsJson ?? {},
|
|
17028
|
+
timeoutSeconds: node.timeoutSeconds ?? null,
|
|
16648
17029
|
retryPolicyJson: null,
|
|
16649
|
-
advancementPolicyDefinition:
|
|
16650
|
-
computedSignalDefinitions:
|
|
17030
|
+
advancementPolicyDefinition: node.advancementPolicyDefinition,
|
|
17031
|
+
computedSignalDefinitions: node.computedSignalDefinitions ?? []
|
|
16651
17032
|
};
|
|
16652
17033
|
});
|
|
16653
17034
|
const body = {
|
|
@@ -16682,7 +17063,12 @@ function makeLeaf(fact, path, operator, value) {
|
|
|
16682
17063
|
return {
|
|
16683
17064
|
_condition: condition,
|
|
16684
17065
|
then(outcome) {
|
|
16685
|
-
return {
|
|
17066
|
+
return {
|
|
17067
|
+
_tag: "assignment_rule",
|
|
17068
|
+
conditions: [condition],
|
|
17069
|
+
mode: "all",
|
|
17070
|
+
outcome
|
|
17071
|
+
};
|
|
16686
17072
|
}
|
|
16687
17073
|
};
|
|
16688
17074
|
}
|
|
@@ -16701,7 +17087,7 @@ function makeFieldRef(fact, path) {
|
|
|
16701
17087
|
};
|
|
16702
17088
|
}
|
|
16703
17089
|
function makeAssign(pipeline2) {
|
|
16704
|
-
if (typeof pipeline2 !== "object" || typeof pipeline2["key"] !== "string" || !Array.isArray(pipeline2["
|
|
17090
|
+
if (typeof pipeline2 !== "object" || typeof pipeline2["key"] !== "string" || !Array.isArray(pipeline2["nodeDefinitions"])) {
|
|
16705
17091
|
throw new Error("assign() requires a pipeline spec produced by pipeline().build(). " + "Pass the default-exported value from a pipeline definition file.");
|
|
16706
17092
|
}
|
|
16707
17093
|
return { _tag: "assign", pipeline: pipeline2 };
|
|
@@ -16789,7 +17175,7 @@ function serializeDefaultPipelineAssignment(spec) {
|
|
|
16789
17175
|
return serializeAssignmentRule(rule);
|
|
16790
17176
|
});
|
|
16791
17177
|
return {
|
|
16792
|
-
|
|
17178
|
+
pipelineDefinitionKey: primaryKey,
|
|
16793
17179
|
rulesJson: { rules: serializedRules },
|
|
16794
17180
|
defaultEventType: defaultType,
|
|
16795
17181
|
defaultEventParamsJson: defaultParams,
|
|
@@ -17087,6 +17473,8 @@ function checkHealthChecks(steps) {
|
|
|
17087
17473
|
return issues;
|
|
17088
17474
|
}
|
|
17089
17475
|
function routeTargets(policy) {
|
|
17476
|
+
if (!policy)
|
|
17477
|
+
return [];
|
|
17090
17478
|
const keys = [];
|
|
17091
17479
|
if (policy.defaultEventType === "route" && typeof policy.defaultEventParamsJson?.["pipelineKey"] === "string") {
|
|
17092
17480
|
keys.push(policy.defaultEventParamsJson["pipelineKey"]);
|
|
@@ -17105,36 +17493,42 @@ function checkRouteTargets(pipelines, knownPipelineKeys) {
|
|
|
17105
17493
|
...knownPipelineKeys
|
|
17106
17494
|
]);
|
|
17107
17495
|
for (const pipeline2 of pipelines) {
|
|
17108
|
-
for (const
|
|
17109
|
-
for (const target of routeTargets(
|
|
17496
|
+
for (const node of pipeline2.nodeDefinitions) {
|
|
17497
|
+
for (const target of routeTargets(node.advancementPolicyDefinition)) {
|
|
17110
17498
|
if (known.has(target))
|
|
17111
17499
|
continue;
|
|
17112
17500
|
issues.push({
|
|
17113
17501
|
check: "route-target",
|
|
17114
|
-
message: `Pipeline "${pipeline2.key}" step "${
|
|
17502
|
+
message: `Pipeline "${pipeline2.key}" step "${node.stepKey ?? node.nodeKey}" routes to pipeline ` + `"${target}", but no pipeline with that key was found on the server or ` + `in the current push batch. Push the target pipeline first.`
|
|
17115
17503
|
});
|
|
17116
17504
|
}
|
|
17117
17505
|
}
|
|
17118
17506
|
}
|
|
17119
17507
|
return issues;
|
|
17120
17508
|
}
|
|
17121
|
-
function executionRanks(
|
|
17122
|
-
const
|
|
17123
|
-
const
|
|
17124
|
-
|
|
17125
|
-
|
|
17509
|
+
function executionRanks(nodeDefinitions, dependencyEdges) {
|
|
17510
|
+
const indexes = nodeDefinitions.map((_, index) => index);
|
|
17511
|
+
const orderedNodes = tryOrderChainNodeDefinitions(nodeDefinitions, dependencyEdges);
|
|
17512
|
+
if (orderedNodes === null) {
|
|
17513
|
+
return new Map(indexes.map((index, rank) => [index, rank]));
|
|
17514
|
+
}
|
|
17515
|
+
const indexByNodeKey = new Map(nodeDefinitions.map((node, index) => [node.nodeKey, index]));
|
|
17516
|
+
const ordered = orderedNodes.map((node) => indexByNodeKey.get(node.nodeKey) ?? 0);
|
|
17126
17517
|
return new Map(ordered.map((index, rank) => [index, rank]));
|
|
17127
17518
|
}
|
|
17128
17519
|
function bindingSource(binding) {
|
|
17129
17520
|
if (binding.source === "step_signal") {
|
|
17130
|
-
return { stepKey: binding.stepKey, signalKey: binding.signalKey };
|
|
17521
|
+
return { stepKey: binding.stepKey, signalKey: binding.signalKey, kind: "signal" };
|
|
17131
17522
|
}
|
|
17132
17523
|
if (binding.source === "step_output") {
|
|
17133
|
-
return { stepKey: binding.stepKey, signalKey: null };
|
|
17524
|
+
return { stepKey: binding.stepKey, signalKey: null, kind: "output" };
|
|
17525
|
+
}
|
|
17526
|
+
if (binding.source === "signals_list") {
|
|
17527
|
+
return { stepKey: binding.stepKey, signalKey: null, kind: "signals_list" };
|
|
17134
17528
|
}
|
|
17135
17529
|
return null;
|
|
17136
17530
|
}
|
|
17137
|
-
function declaredSignalKeys(stepKey, stepsByKey,
|
|
17531
|
+
function declaredSignalKeys(stepKey, stepsByKey, pipelineNodeDefinitions) {
|
|
17138
17532
|
const specs = stepsByKey.get(stepKey);
|
|
17139
17533
|
if (!specs || specs.length === 0)
|
|
17140
17534
|
return null;
|
|
@@ -17143,10 +17537,10 @@ function declaredSignalKeys(stepKey, stepsByKey, pipelineSteps) {
|
|
|
17143
17537
|
for (const signal2 of spec.signalExtractorDefinitions)
|
|
17144
17538
|
keys.add(signal2.key);
|
|
17145
17539
|
}
|
|
17146
|
-
for (const
|
|
17147
|
-
if (
|
|
17540
|
+
for (const node of pipelineNodeDefinitions) {
|
|
17541
|
+
if (node.stepKey !== stepKey)
|
|
17148
17542
|
continue;
|
|
17149
|
-
for (const computed of
|
|
17543
|
+
for (const computed of node.computedSignalDefinitions ?? [])
|
|
17150
17544
|
keys.add(computed.key);
|
|
17151
17545
|
}
|
|
17152
17546
|
return [...keys];
|
|
@@ -17154,18 +17548,18 @@ function declaredSignalKeys(stepKey, stepsByKey, pipelineSteps) {
|
|
|
17154
17548
|
function checkSignalBindings(pipelines, stepsByKey) {
|
|
17155
17549
|
const issues = [];
|
|
17156
17550
|
for (const pipeline2 of pipelines) {
|
|
17157
|
-
const ranks = executionRanks(pipeline2.
|
|
17158
|
-
const order = [...pipeline2.
|
|
17551
|
+
const ranks = executionRanks(pipeline2.nodeDefinitions, pipeline2.dependencyEdges);
|
|
17552
|
+
const order = [...pipeline2.nodeDefinitions.keys()].sort((left, right) => (ranks.get(left) ?? 0) - (ranks.get(right) ?? 0)).map((index) => pipeline2.nodeDefinitions[index]?.stepKey ?? "");
|
|
17159
17553
|
const orderHint = `Steps in "${pipeline2.key}", in order: ${order.join(" \u2192 ")}.`;
|
|
17160
|
-
pipeline2.
|
|
17554
|
+
pipeline2.nodeDefinitions.forEach((node, index) => {
|
|
17161
17555
|
const consumerRank = ranks.get(index) ?? index;
|
|
17162
|
-
const where = `Pipeline "${pipeline2.key}" step "${
|
|
17163
|
-
for (const [field, binding] of Object.entries(
|
|
17556
|
+
const where = `Pipeline "${pipeline2.key}" step "${node.stepKey ?? node.nodeKey}"`;
|
|
17557
|
+
for (const [field, binding] of Object.entries(node.inputBindingsJson ?? {})) {
|
|
17164
17558
|
const source = bindingSource(binding);
|
|
17165
17559
|
if (!source)
|
|
17166
17560
|
continue;
|
|
17167
|
-
const what = source.
|
|
17168
|
-
const producerRanks = pipeline2.
|
|
17561
|
+
const what = source.kind === "signal" ? `binds input "${field}" to signal "${source.signalKey ?? ""}" of step "${source.stepKey}"` : source.kind === "signals_list" ? `binds input "${field}" to the signals list of fan-out step "${source.stepKey}"` : `binds input "${field}" to the output of step "${source.stepKey}"`;
|
|
17562
|
+
const producerRanks = pipeline2.nodeDefinitions.map((candidate, candidateIndex) => candidate.stepKey === source.stepKey ? ranks.get(candidateIndex) ?? candidateIndex : null).filter((rank) => rank !== null);
|
|
17169
17563
|
if (producerRanks.length === 0) {
|
|
17170
17564
|
issues.push({
|
|
17171
17565
|
check: "signal-binding",
|
|
@@ -17182,7 +17576,7 @@ function checkSignalBindings(pipelines, stepsByKey) {
|
|
|
17182
17576
|
}
|
|
17183
17577
|
if (source.signalKey === null)
|
|
17184
17578
|
continue;
|
|
17185
|
-
const available = declaredSignalKeys(source.stepKey, stepsByKey, pipeline2.
|
|
17579
|
+
const available = declaredSignalKeys(source.stepKey, stepsByKey, pipeline2.nodeDefinitions);
|
|
17186
17580
|
if (available === null || available.includes(source.signalKey))
|
|
17187
17581
|
continue;
|
|
17188
17582
|
issues.push({
|
|
@@ -17233,7 +17627,7 @@ function isPipelineDefinitionSpec(value) {
|
|
|
17233
17627
|
if (typeof value !== "object" || value === null)
|
|
17234
17628
|
return false;
|
|
17235
17629
|
const obj = value;
|
|
17236
|
-
return typeof obj["key"] === "string" && typeof obj["name"] === "string" && typeof obj["version"] === "number" && Array.isArray(obj["
|
|
17630
|
+
return typeof obj["key"] === "string" && typeof obj["name"] === "string" && typeof obj["version"] === "number" && Array.isArray(obj["nodeDefinitions"]);
|
|
17237
17631
|
}
|
|
17238
17632
|
async function importModule(path) {
|
|
17239
17633
|
return await import(pathToFileURL(path).href);
|
|
@@ -17331,7 +17725,7 @@ async function syncDefaultPipelineAssignment(spec, opts, headers, pipelinesClien
|
|
|
17331
17725
|
p.id
|
|
17332
17726
|
]));
|
|
17333
17727
|
const referencedKeys = new Set;
|
|
17334
|
-
referencedKeys.add(serialized.
|
|
17728
|
+
referencedKeys.add(serialized.pipelineDefinitionKey);
|
|
17335
17729
|
for (const rule of serialized.rulesJson.rules) {
|
|
17336
17730
|
if (rule.event.type === "assign" && typeof rule.event.params?.["pipelineKey"] === "string") {
|
|
17337
17731
|
referencedKeys.add(rule.event.params["pipelineKey"]);
|
|
@@ -17342,9 +17736,9 @@ async function syncDefaultPipelineAssignment(spec, opts, headers, pipelinesClien
|
|
|
17342
17736
|
throw new Error(`${DEFAULT_PIPELINE_ASSIGNMENT_FILENAME} references pipeline "${key}", ` + `but no pipeline with that key was found on the server. ` + `Push the pipeline first with \`boboddy pipelines push\`.`);
|
|
17343
17737
|
}
|
|
17344
17738
|
}
|
|
17345
|
-
const
|
|
17346
|
-
if (!
|
|
17347
|
-
throw new Error(`Pipeline key "${serialized.
|
|
17739
|
+
const pipelineDefinitionId = pipelineKeyToId.get(serialized.pipelineDefinitionKey);
|
|
17740
|
+
if (!pipelineDefinitionId) {
|
|
17741
|
+
throw new Error(`Pipeline key "${serialized.pipelineDefinitionKey}" was not found on the server.`);
|
|
17348
17742
|
}
|
|
17349
17743
|
const resolvedRules = serialized.rulesJson.rules.map((rule) => {
|
|
17350
17744
|
if (rule.event.type === "assign" && typeof rule.event.params?.["pipelineKey"] === "string") {
|
|
@@ -17373,7 +17767,7 @@ async function syncDefaultPipelineAssignment(spec, opts, headers, pipelinesClien
|
|
|
17373
17767
|
path: { projectId: opts.projectId },
|
|
17374
17768
|
body: {
|
|
17375
17769
|
defaultPipelineAssignment: {
|
|
17376
|
-
|
|
17770
|
+
pipelineDefinitionId,
|
|
17377
17771
|
rulesJson: { rules: resolvedRules },
|
|
17378
17772
|
defaultEventType: serialized.defaultEventType,
|
|
17379
17773
|
defaultEventParamsJson: serialized.defaultEventParamsJson,
|
|
@@ -17385,7 +17779,7 @@ async function syncDefaultPipelineAssignment(spec, opts, headers, pipelinesClien
|
|
|
17385
17779
|
if (result.error) {
|
|
17386
17780
|
throw new Error(`Failed to update project default pipeline assignment: ${JSON.stringify(result.error)}`);
|
|
17387
17781
|
}
|
|
17388
|
-
log(`\u2713 default pipeline assignment \u2192 synced (primary pipeline: ${serialized.
|
|
17782
|
+
log(`\u2713 default pipeline assignment \u2192 synced (primary pipeline: ${serialized.pipelineDefinitionKey})`);
|
|
17389
17783
|
return true;
|
|
17390
17784
|
}
|
|
17391
17785
|
export {
|