@boboddy/sdk 0.3.1 → 0.4.2
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 +93 -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 +7 -7
- 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 +566 -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 +92 -23
- package/dist/definitions/validation/index.js +91 -22
- package/dist/generated/index.d.ts +2 -2
- package/dist/generated/sdk.gen.d.ts +40 -24
- package/dist/generated/types.gen.d.ts +1793 -542
- package/dist/index.js +567 -125
- package/dist/push/index.js +603 -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,32 @@ 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 });
|
|
13268
|
+
}
|
|
13269
|
+
cancelPipelineExecutions(options) {
|
|
13270
|
+
return (options.client ?? this.client).put({
|
|
13271
|
+
url: "/api/pipeline-executions/batch/cancel",
|
|
13272
|
+
...options,
|
|
13273
|
+
headers: {
|
|
13274
|
+
"Content-Type": "application/json",
|
|
13275
|
+
...options.headers
|
|
13276
|
+
}
|
|
13277
|
+
});
|
|
13258
13278
|
}
|
|
13259
13279
|
getPipelineExecution(options) {
|
|
13260
|
-
return (options.client ?? this.client).get({ url: "/api/
|
|
13280
|
+
return (options.client ?? this.client).get({ url: "/api/pipeline-executions/{pipelineExecutionId}", ...options });
|
|
13281
|
+
}
|
|
13282
|
+
getPipelineExecutionRoutedChain(options) {
|
|
13283
|
+
return (options.client ?? this.client).get({ url: "/api/pipeline-executions/{pipelineExecutionId}/routed-chain", ...options });
|
|
13261
13284
|
}
|
|
13262
13285
|
countPipelineExecutionsByPipeline(options) {
|
|
13263
|
-
return (options.client ?? this.client).get({ url: "/api/
|
|
13286
|
+
return (options.client ?? this.client).get({ url: "/api/pipeline-executions/counts/by-pipeline", ...options });
|
|
13264
13287
|
}
|
|
13265
13288
|
listPipelineDefinitionStepRollups(options) {
|
|
13266
|
-
return (options.client ?? this.client).get({ url: "/api/
|
|
13289
|
+
return (options.client ?? this.client).get({ url: "/api/pipeline-executions/step-rollups/by-definition/{pipelineDefinitionId}", ...options });
|
|
13267
13290
|
}
|
|
13268
13291
|
listPipelineDefinitionStepRuns(options) {
|
|
13269
|
-
return (options.client ?? this.client).get({ url: "/api/
|
|
13292
|
+
return (options.client ?? this.client).get({ url: "/api/pipeline-executions/step-runs/by-definition/{pipelineDefinitionId}", ...options });
|
|
13270
13293
|
}
|
|
13271
13294
|
}
|
|
13272
13295
|
|
|
@@ -13277,6 +13300,19 @@ class WorkItems extends HeyApiClient {
|
|
|
13277
13300
|
getWorkItem(options) {
|
|
13278
13301
|
return (options.client ?? this.client).get({ url: "/api/work-items/{workItemId}", ...options });
|
|
13279
13302
|
}
|
|
13303
|
+
editWorkItem(options) {
|
|
13304
|
+
return (options.client ?? this.client).patch({
|
|
13305
|
+
url: "/api/work-items/{workItemId}",
|
|
13306
|
+
...options,
|
|
13307
|
+
headers: {
|
|
13308
|
+
"Content-Type": "application/json",
|
|
13309
|
+
...options.headers
|
|
13310
|
+
}
|
|
13311
|
+
});
|
|
13312
|
+
}
|
|
13313
|
+
listWorkItemChildren(options) {
|
|
13314
|
+
return (options.client ?? this.client).get({ url: "/api/work-items/{workItemId}/children", ...options });
|
|
13315
|
+
}
|
|
13280
13316
|
createWorkItem(options) {
|
|
13281
13317
|
return (options.client ?? this.client).post({
|
|
13282
13318
|
url: "/api/work-items",
|
|
@@ -13327,6 +13363,16 @@ class WorkItems extends HeyApiClient {
|
|
|
13327
13363
|
}
|
|
13328
13364
|
});
|
|
13329
13365
|
}
|
|
13366
|
+
setWorkItemParent(options) {
|
|
13367
|
+
return (options.client ?? this.client).patch({
|
|
13368
|
+
url: "/api/work-items/{workItemId}/parent",
|
|
13369
|
+
...options,
|
|
13370
|
+
headers: {
|
|
13371
|
+
"Content-Type": "application/json",
|
|
13372
|
+
...options.headers
|
|
13373
|
+
}
|
|
13374
|
+
});
|
|
13375
|
+
}
|
|
13330
13376
|
}
|
|
13331
13377
|
|
|
13332
13378
|
class WorkItemComments extends HeyApiClient {
|
|
@@ -13368,6 +13414,25 @@ class WorkItemComments extends HeyApiClient {
|
|
|
13368
13414
|
}
|
|
13369
13415
|
}
|
|
13370
13416
|
|
|
13417
|
+
class WorkItemBlocks extends HeyApiClient {
|
|
13418
|
+
listWorkItemBlocks(options) {
|
|
13419
|
+
return (options.client ?? this.client).get({ url: "/api/work-item-blocks", ...options });
|
|
13420
|
+
}
|
|
13421
|
+
createWorkItemBlock(options) {
|
|
13422
|
+
return (options.client ?? this.client).post({
|
|
13423
|
+
url: "/api/work-item-blocks",
|
|
13424
|
+
...options,
|
|
13425
|
+
headers: {
|
|
13426
|
+
"Content-Type": "application/json",
|
|
13427
|
+
...options.headers
|
|
13428
|
+
}
|
|
13429
|
+
});
|
|
13430
|
+
}
|
|
13431
|
+
deleteWorkItemBlock(options) {
|
|
13432
|
+
return (options.client ?? this.client).delete({ url: "/api/work-item-blocks/{blockId}", ...options });
|
|
13433
|
+
}
|
|
13434
|
+
}
|
|
13435
|
+
|
|
13371
13436
|
class ProjectContext extends HeyApiClient {
|
|
13372
13437
|
listProjectContextEntries(options) {
|
|
13373
13438
|
return (options.client ?? this.client).get({ url: "/api/projects/{projectId}/context-entries", ...options });
|
|
@@ -13576,6 +13641,10 @@ class BoboddyClient extends HeyApiClient {
|
|
|
13576
13641
|
get workItemComments() {
|
|
13577
13642
|
return this._workItemComments ??= new WorkItemComments({ client: this.client });
|
|
13578
13643
|
}
|
|
13644
|
+
_workItemBlocks;
|
|
13645
|
+
get workItemBlocks() {
|
|
13646
|
+
return this._workItemBlocks ??= new WorkItemBlocks({ client: this.client });
|
|
13647
|
+
}
|
|
13579
13648
|
_projectContext;
|
|
13580
13649
|
get projectContext() {
|
|
13581
13650
|
return this._projectContext ??= new ProjectContext({ client: this.client });
|
|
@@ -16205,6 +16274,140 @@ function extractInlineComputedSignals(policy) {
|
|
|
16205
16274
|
return [...byKey.values()];
|
|
16206
16275
|
}
|
|
16207
16276
|
|
|
16277
|
+
// src/definitions/advancement-policies/cohort-advancement-policy.ts
|
|
16278
|
+
var cohortAdvancementEventTypeValues = ["continue", "block"];
|
|
16279
|
+
function serializeCohortCondition(condition) {
|
|
16280
|
+
if (condition._tag === "signal") {
|
|
16281
|
+
return {
|
|
16282
|
+
fact: typeof condition.signal === "string" ? condition.signal : condition.signal.key,
|
|
16283
|
+
operator: condition.operator,
|
|
16284
|
+
value: condition.value
|
|
16285
|
+
};
|
|
16286
|
+
}
|
|
16287
|
+
if (condition._tag === "all") {
|
|
16288
|
+
return { all: condition.conditions.map(serializeCohortCondition) };
|
|
16289
|
+
}
|
|
16290
|
+
return { any: condition.conditions.map(serializeCohortCondition) };
|
|
16291
|
+
}
|
|
16292
|
+
function serializeCohortRule(rule) {
|
|
16293
|
+
return {
|
|
16294
|
+
conditions: { [rule.mode]: rule.conditions.map(serializeCohortCondition) },
|
|
16295
|
+
event: {
|
|
16296
|
+
type: rule.outcome,
|
|
16297
|
+
...rule.outcomeJson ? { params: rule.outcomeJson } : {}
|
|
16298
|
+
}
|
|
16299
|
+
};
|
|
16300
|
+
}
|
|
16301
|
+
function serializeCohortAdvancementPolicy(policy) {
|
|
16302
|
+
if (!policy) {
|
|
16303
|
+
return { rules: [], defaultEventType: "continue", defaultEventParamsJson: null };
|
|
16304
|
+
}
|
|
16305
|
+
return {
|
|
16306
|
+
rules: (policy.rules ?? []).map(serializeCohortRule),
|
|
16307
|
+
defaultEventType: policy.default,
|
|
16308
|
+
defaultEventParamsJson: policy.defaultParamsJson ?? null
|
|
16309
|
+
};
|
|
16310
|
+
}
|
|
16311
|
+
function visitCohortSignalConditions(conditions, visit) {
|
|
16312
|
+
for (const c of conditions) {
|
|
16313
|
+
if (c._tag === "signal") {
|
|
16314
|
+
visit(c);
|
|
16315
|
+
} else {
|
|
16316
|
+
visitCohortSignalConditions(c.conditions, visit);
|
|
16317
|
+
}
|
|
16318
|
+
}
|
|
16319
|
+
}
|
|
16320
|
+
function isSameStepSignalsListDefinition(a, b) {
|
|
16321
|
+
return JSON.stringify(a.ops) === JSON.stringify(b.ops) && JSON.stringify(a.reducer) === JSON.stringify(b.reducer);
|
|
16322
|
+
}
|
|
16323
|
+
function extractInlineStepSignalsListDefinitions(policy) {
|
|
16324
|
+
if (!policy?.rules)
|
|
16325
|
+
return [];
|
|
16326
|
+
const byKey = new Map;
|
|
16327
|
+
for (const rule of policy.rules) {
|
|
16328
|
+
visitCohortSignalConditions(rule.conditions, (cond) => {
|
|
16329
|
+
if (typeof cond.signal === "string")
|
|
16330
|
+
return;
|
|
16331
|
+
const inline = cond.signal;
|
|
16332
|
+
const def = {
|
|
16333
|
+
key: inline.key,
|
|
16334
|
+
ops: inline.ops,
|
|
16335
|
+
reducer: inline.reducer
|
|
16336
|
+
};
|
|
16337
|
+
const existing = byKey.get(def.key);
|
|
16338
|
+
if (existing) {
|
|
16339
|
+
if (!isSameStepSignalsListDefinition(existing, def)) {
|
|
16340
|
+
throw new Error(`Conflicting inline stepSignalsList definitions for key "${def.key}"`);
|
|
16341
|
+
}
|
|
16342
|
+
return;
|
|
16343
|
+
}
|
|
16344
|
+
byKey.set(def.key, def);
|
|
16345
|
+
});
|
|
16346
|
+
}
|
|
16347
|
+
return [...byKey.values()];
|
|
16348
|
+
}
|
|
16349
|
+
|
|
16350
|
+
// src/definitions/pipelines/chain-graph.ts
|
|
16351
|
+
function tryOrderChainNodeDefinitions(nodeDefinitions, dependencyEdges) {
|
|
16352
|
+
const nodesByKey = new Map;
|
|
16353
|
+
for (const nodeDefinition of nodeDefinitions) {
|
|
16354
|
+
nodesByKey.set(nodeDefinition.nodeKey, nodeDefinition);
|
|
16355
|
+
}
|
|
16356
|
+
const outgoing = new Map;
|
|
16357
|
+
const incomingCount = new Map;
|
|
16358
|
+
for (const nodeDefinition of nodeDefinitions) {
|
|
16359
|
+
incomingCount.set(nodeDefinition.nodeKey, 0);
|
|
16360
|
+
}
|
|
16361
|
+
for (const edge of dependencyEdges) {
|
|
16362
|
+
if (!nodesByKey.has(edge.fromNodeKey) || !nodesByKey.has(edge.toNodeKey)) {
|
|
16363
|
+
return null;
|
|
16364
|
+
}
|
|
16365
|
+
if (outgoing.has(edge.fromNodeKey))
|
|
16366
|
+
return null;
|
|
16367
|
+
outgoing.set(edge.fromNodeKey, edge.toNodeKey);
|
|
16368
|
+
incomingCount.set(edge.toNodeKey, (incomingCount.get(edge.toNodeKey) ?? 0) + 1);
|
|
16369
|
+
}
|
|
16370
|
+
for (const count of incomingCount.values()) {
|
|
16371
|
+
if (count > 1)
|
|
16372
|
+
return null;
|
|
16373
|
+
}
|
|
16374
|
+
if (nodeDefinitions.length === 0)
|
|
16375
|
+
return [];
|
|
16376
|
+
const roots = nodeDefinitions.filter((nodeDefinition) => (incomingCount.get(nodeDefinition.nodeKey) ?? 0) === 0);
|
|
16377
|
+
if (roots.length !== 1)
|
|
16378
|
+
return null;
|
|
16379
|
+
const rootNode = roots[0];
|
|
16380
|
+
if (!rootNode)
|
|
16381
|
+
return null;
|
|
16382
|
+
const ordered = [];
|
|
16383
|
+
const visited = new Set;
|
|
16384
|
+
let currentKey = rootNode.nodeKey;
|
|
16385
|
+
while (currentKey !== undefined) {
|
|
16386
|
+
if (visited.has(currentKey))
|
|
16387
|
+
return null;
|
|
16388
|
+
visited.add(currentKey);
|
|
16389
|
+
const currentNode = nodesByKey.get(currentKey);
|
|
16390
|
+
if (!currentNode)
|
|
16391
|
+
return null;
|
|
16392
|
+
ordered.push(currentNode);
|
|
16393
|
+
currentKey = outgoing.get(currentKey);
|
|
16394
|
+
}
|
|
16395
|
+
if (ordered.length !== nodeDefinitions.length)
|
|
16396
|
+
return null;
|
|
16397
|
+
return ordered;
|
|
16398
|
+
}
|
|
16399
|
+
function buildChainDependencyEdges(orderedNodes) {
|
|
16400
|
+
const dependencyEdges = [];
|
|
16401
|
+
for (let index = 0;index < orderedNodes.length - 1; index += 1) {
|
|
16402
|
+
const from = orderedNodes[index];
|
|
16403
|
+
const to = orderedNodes[index + 1];
|
|
16404
|
+
if (!from || !to)
|
|
16405
|
+
continue;
|
|
16406
|
+
dependencyEdges.push({ fromNodeKey: from.nodeKey, toNodeKey: to.nodeKey });
|
|
16407
|
+
}
|
|
16408
|
+
return dependencyEdges;
|
|
16409
|
+
}
|
|
16410
|
+
|
|
16208
16411
|
// src/definitions/pipelines/define-pipeline.ts
|
|
16209
16412
|
function serializeBinding(binding) {
|
|
16210
16413
|
if (binding.source === "pipeline_input") {
|
|
@@ -16223,15 +16426,42 @@ function serializeBinding(binding) {
|
|
|
16223
16426
|
if (binding.source === "literal") {
|
|
16224
16427
|
return { source: "literal", value: binding.value };
|
|
16225
16428
|
}
|
|
16429
|
+
if (binding.source === "signals_list") {
|
|
16430
|
+
return { source: "signals_list", stepKey: binding.fanOutStep.key };
|
|
16431
|
+
}
|
|
16432
|
+
if (binding.source === "fan_out_item") {
|
|
16433
|
+
return { source: "fan_out_item" };
|
|
16434
|
+
}
|
|
16226
16435
|
return { source: "step_output", stepKey: binding.step.key };
|
|
16227
16436
|
}
|
|
16437
|
+
var isFanOutConfig = (node) => ("nodeType" in node) && node.nodeType === "fanOut";
|
|
16438
|
+
var isCohortGateConfig = (node) => ("nodeType" in node) && node.nodeType === "cohortGate";
|
|
16439
|
+
function serializeInputBindings(input, pipelineInputBindings) {
|
|
16440
|
+
const autoBindings = {
|
|
16441
|
+
workItemTitle: { source: "work_item", field: "title" },
|
|
16442
|
+
workItemDescription: { source: "work_item", field: "description" }
|
|
16443
|
+
};
|
|
16444
|
+
const pipelineBindings = {};
|
|
16445
|
+
for (const [key, binding] of Object.entries(pipelineInputBindings ?? {})) {
|
|
16446
|
+
pipelineBindings[key] = serializeBinding(binding);
|
|
16447
|
+
}
|
|
16448
|
+
const explicitBindings = Object.fromEntries(Object.entries(input ?? {}).filter((entry) => entry[1] !== undefined).map(([key, binding]) => [key, serializeBinding(binding)]));
|
|
16449
|
+
return { ...autoBindings, ...pipelineBindings, ...explicitBindings };
|
|
16450
|
+
}
|
|
16228
16451
|
function buildPipelineSpec(config2) {
|
|
16229
|
-
const
|
|
16452
|
+
const nodes = config2.nodes;
|
|
16230
16453
|
const stepDefMap = new Map;
|
|
16231
|
-
|
|
16232
|
-
const mapKey = `${
|
|
16454
|
+
const registerStepDef = (step) => {
|
|
16455
|
+
const mapKey = `${step.key}@v${String(step.version)}`;
|
|
16233
16456
|
if (!stepDefMap.has(mapKey)) {
|
|
16234
|
-
stepDefMap.set(mapKey,
|
|
16457
|
+
stepDefMap.set(mapKey, step);
|
|
16458
|
+
}
|
|
16459
|
+
};
|
|
16460
|
+
for (const node of nodes) {
|
|
16461
|
+
if (isFanOutConfig(node)) {
|
|
16462
|
+
registerStepDef(node.fanOutStep);
|
|
16463
|
+
} else if (!isCohortGateConfig(node)) {
|
|
16464
|
+
registerStepDef(node.step);
|
|
16235
16465
|
}
|
|
16236
16466
|
}
|
|
16237
16467
|
let inputSchemaJson = null;
|
|
@@ -16242,6 +16472,46 @@ function buildPipelineSpec(config2) {
|
|
|
16242
16472
|
inputSchemaJson = null;
|
|
16243
16473
|
}
|
|
16244
16474
|
}
|
|
16475
|
+
const nodeDefinitions = nodes.map((node) => {
|
|
16476
|
+
if (isCohortGateConfig(node)) {
|
|
16477
|
+
const serializedPolicy = serializeCohortAdvancementPolicy(node.advanceAll);
|
|
16478
|
+
const inlineStepSignalsListDefinitions = extractInlineStepSignalsListDefinitions(node.advanceAll);
|
|
16479
|
+
return {
|
|
16480
|
+
nodeKey: node.nodeKey,
|
|
16481
|
+
kind: "cohortGate",
|
|
16482
|
+
advanceAllPolicyDefinition: serializedPolicy,
|
|
16483
|
+
stepSignalsListDefinitions: [
|
|
16484
|
+
...inlineStepSignalsListDefinitions,
|
|
16485
|
+
...node.stepSignalsListDefinitions ?? []
|
|
16486
|
+
]
|
|
16487
|
+
};
|
|
16488
|
+
}
|
|
16489
|
+
if (isFanOutConfig(node)) {
|
|
16490
|
+
return {
|
|
16491
|
+
nodeKey: node.fanOutStep.key,
|
|
16492
|
+
kind: "fanOut",
|
|
16493
|
+
stepKey: node.fanOutStep.key,
|
|
16494
|
+
stepName: node.fanOutStep.name,
|
|
16495
|
+
stepDescription: node.fanOutStep.description,
|
|
16496
|
+
inputBindingsJson: serializeInputBindings(node.input, config2.pipelineInputBindings),
|
|
16497
|
+
timeoutSeconds: node.timeout ?? null,
|
|
16498
|
+
overSignalKey: node.overSignalKey,
|
|
16499
|
+
advanceEachPolicyDefinition: serializeCohortAdvancementPolicy(node.advanceEach)
|
|
16500
|
+
};
|
|
16501
|
+
}
|
|
16502
|
+
return {
|
|
16503
|
+
nodeKey: node.step.key,
|
|
16504
|
+
kind: "step",
|
|
16505
|
+
stepKey: node.step.key,
|
|
16506
|
+
stepName: node.step.name,
|
|
16507
|
+
stepDescription: node.step.description,
|
|
16508
|
+
inputBindingsJson: serializeInputBindings(node.input, config2.pipelineInputBindings),
|
|
16509
|
+
timeoutSeconds: node.timeout ?? null,
|
|
16510
|
+
advancementPolicyDefinition: serializeAdvancementPolicy(node.advancement),
|
|
16511
|
+
computedSignalDefinitions: extractInlineComputedSignals(node.advancement)
|
|
16512
|
+
};
|
|
16513
|
+
});
|
|
16514
|
+
const dependencyEdges = buildChainDependencyEdges(nodeDefinitions);
|
|
16245
16515
|
return {
|
|
16246
16516
|
key: config2.key,
|
|
16247
16517
|
name: config2.name,
|
|
@@ -16250,31 +16520,8 @@ function buildPipelineSpec(config2) {
|
|
|
16250
16520
|
status: config2.status ?? "active",
|
|
16251
16521
|
inputSchemaJson,
|
|
16252
16522
|
_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
|
-
})
|
|
16523
|
+
nodeDefinitions,
|
|
16524
|
+
dependencyEdges
|
|
16278
16525
|
};
|
|
16279
16526
|
}
|
|
16280
16527
|
// src/definitions/advancement-policies/fluent-rules.ts
|
|
@@ -16445,7 +16692,10 @@ function makeStepInputCtx(inputSchema) {
|
|
|
16445
16692
|
output(step) {
|
|
16446
16693
|
return { source: "step_output", step };
|
|
16447
16694
|
},
|
|
16448
|
-
literal: literal2
|
|
16695
|
+
literal: literal2,
|
|
16696
|
+
signalsList(fanOutStep) {
|
|
16697
|
+
return { source: "signals_list", fanOutStep };
|
|
16698
|
+
}
|
|
16449
16699
|
};
|
|
16450
16700
|
}
|
|
16451
16701
|
function literal2(value) {
|
|
@@ -16490,61 +16740,247 @@ function mergeStepBindings(pipelineBindings, explicitBindings) {
|
|
|
16490
16740
|
return Object.keys(merged).length > 0 ? merged : undefined;
|
|
16491
16741
|
}
|
|
16492
16742
|
|
|
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 } : {}
|
|
16743
|
+
// src/definitions/advancement-policies/cohort-fluent-rules.ts
|
|
16744
|
+
var LEAF_BRAND2 = Symbol("boboddy.cohortRule.leaf");
|
|
16745
|
+
var GROUP_BRAND2 = Symbol("boboddy.cohortRule.group");
|
|
16746
|
+
function createCohortSignalRef(signal2) {
|
|
16747
|
+
const leaf = (operator, value) => {
|
|
16748
|
+
const condition = {
|
|
16749
|
+
_tag: "signal",
|
|
16750
|
+
signal: signal2,
|
|
16751
|
+
operator,
|
|
16752
|
+
value
|
|
16516
16753
|
};
|
|
16517
|
-
|
|
16518
|
-
|
|
16519
|
-
|
|
16754
|
+
return {
|
|
16755
|
+
[LEAF_BRAND2]: condition,
|
|
16756
|
+
then(outcome, paramsJson) {
|
|
16757
|
+
return {
|
|
16758
|
+
_tag: "rule",
|
|
16759
|
+
mode: "all",
|
|
16760
|
+
conditions: [condition],
|
|
16761
|
+
outcome,
|
|
16762
|
+
...paramsJson ? { outcomeJson: paramsJson } : {}
|
|
16763
|
+
};
|
|
16764
|
+
}
|
|
16765
|
+
};
|
|
16766
|
+
};
|
|
16767
|
+
return {
|
|
16768
|
+
eq: (v) => leaf("equal", v),
|
|
16769
|
+
ne: (v) => leaf("notEqual", v),
|
|
16770
|
+
gt: (v) => leaf("greaterThan", v),
|
|
16771
|
+
gte: (v) => leaf("greaterThanInclusive", v),
|
|
16772
|
+
lt: (v) => leaf("lessThan", v),
|
|
16773
|
+
lte: (v) => leaf("lessThanInclusive", v),
|
|
16774
|
+
in: (vs) => leaf("in", vs),
|
|
16775
|
+
notIn: (vs) => leaf("notIn", vs),
|
|
16776
|
+
contains: (v) => leaf("contains", v),
|
|
16777
|
+
doesNotContain: (v) => leaf("doesNotContain", v)
|
|
16778
|
+
};
|
|
16779
|
+
}
|
|
16780
|
+
function createCohortLeafFromCondition(condition) {
|
|
16781
|
+
return {
|
|
16782
|
+
[LEAF_BRAND2]: condition,
|
|
16783
|
+
then(outcome, paramsJson) {
|
|
16784
|
+
return {
|
|
16785
|
+
_tag: "rule",
|
|
16786
|
+
mode: "all",
|
|
16787
|
+
conditions: [condition],
|
|
16788
|
+
outcome,
|
|
16789
|
+
...paramsJson ? { outcomeJson: paramsJson } : {}
|
|
16790
|
+
};
|
|
16791
|
+
}
|
|
16792
|
+
};
|
|
16793
|
+
}
|
|
16794
|
+
function extractCohortCondition(ref) {
|
|
16795
|
+
if (LEAF_BRAND2 in ref)
|
|
16796
|
+
return ref[LEAF_BRAND2];
|
|
16797
|
+
const group = ref[GROUP_BRAND2];
|
|
16798
|
+
return group.mode === "all" ? { _tag: "all", conditions: group.conditions } : { _tag: "any", conditions: group.conditions };
|
|
16799
|
+
}
|
|
16800
|
+
function createCohortGroup(mode, refs) {
|
|
16801
|
+
const conditions = refs.map(extractCohortCondition);
|
|
16802
|
+
return {
|
|
16803
|
+
[GROUP_BRAND2]: { mode, conditions },
|
|
16804
|
+
then(outcome, paramsJson) {
|
|
16805
|
+
return {
|
|
16806
|
+
_tag: "rule",
|
|
16807
|
+
mode,
|
|
16808
|
+
conditions,
|
|
16809
|
+
outcome,
|
|
16810
|
+
...paramsJson ? { outcomeJson: paramsJson } : {}
|
|
16811
|
+
};
|
|
16812
|
+
}
|
|
16813
|
+
};
|
|
16814
|
+
}
|
|
16815
|
+
function makeKeyedCohortSignalRef(key) {
|
|
16816
|
+
return createCohortSignalRef(key);
|
|
16817
|
+
}
|
|
16818
|
+
function makeAdvanceEachCtx() {
|
|
16819
|
+
return {
|
|
16820
|
+
signal: (key) => makeKeyedCohortSignalRef(key),
|
|
16821
|
+
stepSignals: new Proxy({}, {
|
|
16822
|
+
get(_, key) {
|
|
16823
|
+
if (typeof key === "string")
|
|
16824
|
+
return makeKeyedCohortSignalRef(key);
|
|
16825
|
+
return;
|
|
16826
|
+
}
|
|
16827
|
+
}),
|
|
16828
|
+
all: (...refs) => createCohortGroup("all", refs),
|
|
16829
|
+
any: (...refs) => createCohortGroup("any", refs)
|
|
16830
|
+
};
|
|
16831
|
+
}
|
|
16832
|
+
var branchOutcomeValues = [
|
|
16833
|
+
"continue",
|
|
16834
|
+
"block",
|
|
16835
|
+
"error",
|
|
16836
|
+
"abandoned"
|
|
16837
|
+
];
|
|
16838
|
+
function summarizeTransformOp(op) {
|
|
16839
|
+
if (op.op === "filter") {
|
|
16840
|
+
return `filter_${op.operator}_${JSON.stringify(op.value)}`;
|
|
16841
|
+
}
|
|
16842
|
+
if (op.op === "sortBy") {
|
|
16843
|
+
return `sortBy_${op.direction}`;
|
|
16844
|
+
}
|
|
16845
|
+
return "unique";
|
|
16846
|
+
}
|
|
16847
|
+
function deriveStepSignalsListKey(ops, reducer) {
|
|
16848
|
+
const pluck = ops.find((op) => op.op === "pluck");
|
|
16849
|
+
const base = `${reducer.op}_${pluck?.signalKey ?? "value"}`;
|
|
16850
|
+
const extras = ops.filter((op) => op.op !== "pluck").map(summarizeTransformOp);
|
|
16851
|
+
const reducerExtra = reducer.op === "join" ? `sep_${reducer.separator}` : null;
|
|
16852
|
+
const suffixParts = [...extras, ...reducerExtra ? [reducerExtra] : []];
|
|
16853
|
+
return suffixParts.length > 0 ? `${base}_${suffixParts.join("_")}` : base;
|
|
16854
|
+
}
|
|
16855
|
+
function createStepSignalsListBuilder(ops) {
|
|
16856
|
+
const withOp = (op) => createStepSignalsListBuilder([...ops, op]);
|
|
16857
|
+
const reduce = (reducer) => {
|
|
16858
|
+
const token = {
|
|
16859
|
+
_tag: "step_signals_list",
|
|
16860
|
+
key: deriveStepSignalsListKey(ops, reducer),
|
|
16861
|
+
ops: [...ops],
|
|
16862
|
+
reducer
|
|
16863
|
+
};
|
|
16864
|
+
return createCohortSignalRef(token);
|
|
16865
|
+
};
|
|
16866
|
+
return {
|
|
16867
|
+
filter: (operator, value) => withOp({ op: "filter", operator, value }),
|
|
16868
|
+
sortBy: (direction = "asc") => withOp({ op: "sortBy", direction }),
|
|
16869
|
+
unique: () => withOp({ op: "unique" }),
|
|
16870
|
+
count: () => reduce({ op: "count" }),
|
|
16871
|
+
sum: () => reduce({ op: "sum" }),
|
|
16872
|
+
avg: () => reduce({ op: "avg" }),
|
|
16873
|
+
min: () => reduce({ op: "min" }),
|
|
16874
|
+
max: () => reduce({ op: "max" }),
|
|
16875
|
+
booleanAll: () => reduce({ op: "booleanAll" }),
|
|
16876
|
+
booleanAny: () => reduce({ op: "booleanAny" }),
|
|
16877
|
+
join: (separator = ",") => reduce({ op: "join", separator }),
|
|
16878
|
+
first: () => reduce({ op: "first" }),
|
|
16879
|
+
last: () => reduce({ op: "last" })
|
|
16880
|
+
};
|
|
16881
|
+
}
|
|
16882
|
+
function makeAdvanceAllCtx() {
|
|
16883
|
+
return {
|
|
16884
|
+
branchOutcomes: {
|
|
16885
|
+
total: () => createCohortSignalRef("branchCount"),
|
|
16886
|
+
count: (outcome) => createCohortSignalRef(`${outcome}Count`),
|
|
16887
|
+
every: (outcome) => createCohortLeafFromCondition({
|
|
16888
|
+
_tag: "signal",
|
|
16889
|
+
signal: `${outcome}Count`,
|
|
16890
|
+
operator: "equal",
|
|
16891
|
+
value: { fact: "branchCount" }
|
|
16892
|
+
}),
|
|
16893
|
+
some: (outcome) => createCohortLeafFromCondition({
|
|
16894
|
+
_tag: "signal",
|
|
16895
|
+
signal: `${outcome}Count`,
|
|
16896
|
+
operator: "greaterThan",
|
|
16897
|
+
value: 0
|
|
16898
|
+
})
|
|
16899
|
+
},
|
|
16900
|
+
stepSignalsList: {
|
|
16901
|
+
pluck: (signalKey) => createStepSignalsListBuilder([{ op: "pluck", signalKey }])
|
|
16902
|
+
},
|
|
16903
|
+
all: (...refs) => createCohortGroup("all", refs),
|
|
16904
|
+
any: (...refs) => createCohortGroup("any", refs)
|
|
16905
|
+
};
|
|
16906
|
+
}
|
|
16907
|
+
|
|
16908
|
+
// src/definitions/pipelines/fan-out-builder.ts
|
|
16909
|
+
function beginFanOut(inputSchema, meta3, nodes, pipelineInputBindings, pipelineStepInputBindings, step, config2) {
|
|
16910
|
+
const baseCtx = makeStepInputCtx(inputSchema);
|
|
16911
|
+
const ctx = {
|
|
16912
|
+
...baseCtx,
|
|
16913
|
+
item: { source: "fan_out_item" }
|
|
16914
|
+
};
|
|
16915
|
+
const rawInput = config2.input ? config2.input(ctx) : {};
|
|
16916
|
+
const input = mergeStepBindings(pipelineStepInputBindings, normalizeInputMapping(rawInput));
|
|
16917
|
+
const fanOutNodeConfig = {
|
|
16918
|
+
nodeType: "fanOut",
|
|
16919
|
+
fanOutStep: step,
|
|
16920
|
+
overSignalKey: config2.over,
|
|
16921
|
+
...input ? { input } : {},
|
|
16922
|
+
...config2.timeout !== undefined ? { timeout: config2.timeout } : {}
|
|
16923
|
+
};
|
|
16924
|
+
const advanceEachCtx = makeAdvanceEachCtx();
|
|
16925
|
+
const advanceEachResult = config2.advance(advanceEachCtx);
|
|
16926
|
+
const advanceEachPolicy = {
|
|
16927
|
+
default: advanceEachResult.default,
|
|
16928
|
+
...advanceEachResult.rules !== undefined ? { rules: advanceEachResult.rules } : {}
|
|
16929
|
+
};
|
|
16930
|
+
fanOutNodeConfig.advanceEach = advanceEachPolicy;
|
|
16931
|
+
const cohortGateNodeConfig = {
|
|
16932
|
+
nodeType: "cohortGate",
|
|
16933
|
+
nodeKey: `${step.key}__cohortGate`
|
|
16934
|
+
};
|
|
16935
|
+
const advanceAllCtx = makeAdvanceAllCtx();
|
|
16936
|
+
const advanceAllResult = config2.advanceAll(advanceAllCtx);
|
|
16937
|
+
const advanceAllPolicy = {
|
|
16938
|
+
default: advanceAllResult.default,
|
|
16939
|
+
...advanceAllResult.rules !== undefined ? { rules: advanceAllResult.rules } : {}
|
|
16940
|
+
};
|
|
16941
|
+
cohortGateNodeConfig.advanceAll = advanceAllPolicy;
|
|
16942
|
+
nodes.push(fanOutNodeConfig, cohortGateNodeConfig);
|
|
16943
|
+
return new PipelineStepBuilder(inputSchema, meta3, nodes, pipelineInputBindings, pipelineStepInputBindings);
|
|
16944
|
+
}
|
|
16945
|
+
|
|
16946
|
+
// src/definitions/pipelines/builder.ts
|
|
16947
|
+
function pushStep(inputSchema, meta3, nodes, pipelineInputBindings, pipelineStepInputBindings, step, rawOptions) {
|
|
16948
|
+
const options = rawOptions;
|
|
16949
|
+
const ctx = makeStepInputCtx(inputSchema);
|
|
16950
|
+
const rawInput = options.input ? options.input(ctx) : {};
|
|
16951
|
+
const input = mergeStepBindings(pipelineStepInputBindings, normalizeInputMapping(rawInput));
|
|
16952
|
+
const stepConfig = { step, input };
|
|
16953
|
+
if (options.timeout !== undefined)
|
|
16954
|
+
stepConfig.timeout = options.timeout;
|
|
16955
|
+
const advanceCtx = makeAdvanceCtx();
|
|
16956
|
+
const result = options.advance(advanceCtx);
|
|
16957
|
+
const policy = {
|
|
16958
|
+
defaultOutcome: result.default,
|
|
16959
|
+
...result.rules !== undefined ? { rules: result.rules } : {}
|
|
16960
|
+
};
|
|
16961
|
+
stepConfig.advancement = policy;
|
|
16962
|
+
nodes.push(stepConfig);
|
|
16963
|
+
return new PipelineStepBuilder(inputSchema, meta3, nodes, pipelineInputBindings, pipelineStepInputBindings);
|
|
16520
16964
|
}
|
|
16521
16965
|
|
|
16522
16966
|
class PipelineStepBuilder {
|
|
16523
16967
|
inputSchema;
|
|
16524
16968
|
meta;
|
|
16525
|
-
|
|
16969
|
+
nodes;
|
|
16526
16970
|
pipelineInputBindings;
|
|
16527
16971
|
pipelineStepInputBindings;
|
|
16528
|
-
constructor(inputSchema, meta3,
|
|
16972
|
+
constructor(inputSchema, meta3, nodes, pipelineInputBindings = {}, pipelineStepInputBindings = {}) {
|
|
16529
16973
|
this.inputSchema = inputSchema;
|
|
16530
16974
|
this.meta = meta3;
|
|
16531
|
-
this.
|
|
16975
|
+
this.nodes = nodes;
|
|
16532
16976
|
this.pipelineInputBindings = pipelineInputBindings;
|
|
16533
16977
|
this.pipelineStepInputBindings = pipelineStepInputBindings;
|
|
16534
16978
|
}
|
|
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);
|
|
16979
|
+
step(step, options) {
|
|
16980
|
+
return pushStep(this.inputSchema, this.meta, this.nodes, this.pipelineInputBindings, this.pipelineStepInputBindings, step, options);
|
|
16981
|
+
}
|
|
16982
|
+
fanOutStep(step, config2) {
|
|
16983
|
+
return beginFanOut(this.inputSchema, this.meta, this.nodes, this.pipelineInputBindings, this.pipelineStepInputBindings, step, config2);
|
|
16548
16984
|
}
|
|
16549
16985
|
build() {
|
|
16550
16986
|
const config2 = {
|
|
@@ -16554,7 +16990,7 @@ class PipelineStepBuilder {
|
|
|
16554
16990
|
version: this.meta.version,
|
|
16555
16991
|
status: this.meta.status,
|
|
16556
16992
|
input: this.inputSchema,
|
|
16557
|
-
|
|
16993
|
+
nodes: this.nodes,
|
|
16558
16994
|
pipelineInputBindings: this.pipelineInputBindings
|
|
16559
16995
|
};
|
|
16560
16996
|
return buildPipelineSpec(config2);
|
|
@@ -16564,7 +17000,7 @@ class PipelineStepBuilder {
|
|
|
16564
17000
|
class PipelineBuilder {
|
|
16565
17001
|
inputSchema;
|
|
16566
17002
|
meta;
|
|
16567
|
-
|
|
17003
|
+
nodes = [];
|
|
16568
17004
|
pipelineInputBindings;
|
|
16569
17005
|
pipelineStepInputBindings;
|
|
16570
17006
|
constructor(meta3) {
|
|
@@ -16589,19 +17025,8 @@ class PipelineBuilder {
|
|
|
16589
17025
|
}
|
|
16590
17026
|
this.pipelineStepInputBindings = resolveAdditionalStepInputBindings("additionalStepInput", additionalStepInput);
|
|
16591
17027
|
}
|
|
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);
|
|
17028
|
+
step(step, options) {
|
|
17029
|
+
return pushStep(this.inputSchema, this.meta, this.nodes, this.pipelineInputBindings, this.pipelineStepInputBindings, step, options);
|
|
16605
17030
|
}
|
|
16606
17031
|
}
|
|
16607
17032
|
function pipeline(meta3) {
|
|
@@ -16631,23 +17056,35 @@ var buildPipelineDefinitionsClient = (pipelineDefinitions) => {
|
|
|
16631
17056
|
stepDefMap.set(s.key, s);
|
|
16632
17057
|
}
|
|
16633
17058
|
}
|
|
16634
|
-
const
|
|
16635
|
-
|
|
17059
|
+
const nonStepNode = spec.nodeDefinitions.find((node) => node.kind !== "step");
|
|
17060
|
+
if (nonStepNode) {
|
|
17061
|
+
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.`);
|
|
17062
|
+
}
|
|
17063
|
+
const ordered = tryOrderChainNodeDefinitions(spec.nodeDefinitions, spec.dependencyEdges);
|
|
17064
|
+
if (ordered === null) {
|
|
17065
|
+
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.`);
|
|
17066
|
+
}
|
|
17067
|
+
const stepDefinitions = ordered.map((node, index) => {
|
|
17068
|
+
const stepKey = node.stepKey;
|
|
17069
|
+
if (!stepKey) {
|
|
17070
|
+
throw new Error(`Node "${node.nodeKey}" in pipeline "${spec.key}" has no stepKey.`);
|
|
17071
|
+
}
|
|
17072
|
+
const stepDef = stepDefMap.get(stepKey);
|
|
16636
17073
|
if (!stepDef) {
|
|
16637
|
-
throw new Error(`Step "${
|
|
17074
|
+
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
17075
|
}
|
|
16639
17076
|
return {
|
|
16640
17077
|
stepDefinitionId: stepDef.id,
|
|
16641
17078
|
stepDefinitionVersion: stepDef.version,
|
|
16642
|
-
key:
|
|
16643
|
-
name:
|
|
16644
|
-
description:
|
|
16645
|
-
position:
|
|
16646
|
-
inputBindingsJson:
|
|
16647
|
-
timeoutSeconds:
|
|
17079
|
+
key: node.nodeKey,
|
|
17080
|
+
name: node.stepName ?? "",
|
|
17081
|
+
description: node.stepDescription ?? null,
|
|
17082
|
+
position: index + 1,
|
|
17083
|
+
inputBindingsJson: node.inputBindingsJson ?? {},
|
|
17084
|
+
timeoutSeconds: node.timeoutSeconds ?? null,
|
|
16648
17085
|
retryPolicyJson: null,
|
|
16649
|
-
advancementPolicyDefinition:
|
|
16650
|
-
computedSignalDefinitions:
|
|
17086
|
+
advancementPolicyDefinition: node.advancementPolicyDefinition,
|
|
17087
|
+
computedSignalDefinitions: node.computedSignalDefinitions ?? []
|
|
16651
17088
|
};
|
|
16652
17089
|
});
|
|
16653
17090
|
const body = {
|
|
@@ -16682,7 +17119,12 @@ function makeLeaf(fact, path, operator, value) {
|
|
|
16682
17119
|
return {
|
|
16683
17120
|
_condition: condition,
|
|
16684
17121
|
then(outcome) {
|
|
16685
|
-
return {
|
|
17122
|
+
return {
|
|
17123
|
+
_tag: "assignment_rule",
|
|
17124
|
+
conditions: [condition],
|
|
17125
|
+
mode: "all",
|
|
17126
|
+
outcome
|
|
17127
|
+
};
|
|
16686
17128
|
}
|
|
16687
17129
|
};
|
|
16688
17130
|
}
|
|
@@ -16701,7 +17143,7 @@ function makeFieldRef(fact, path) {
|
|
|
16701
17143
|
};
|
|
16702
17144
|
}
|
|
16703
17145
|
function makeAssign(pipeline2) {
|
|
16704
|
-
if (typeof pipeline2 !== "object" || typeof pipeline2["key"] !== "string" || !Array.isArray(pipeline2["
|
|
17146
|
+
if (typeof pipeline2 !== "object" || typeof pipeline2["key"] !== "string" || !Array.isArray(pipeline2["nodeDefinitions"])) {
|
|
16705
17147
|
throw new Error("assign() requires a pipeline spec produced by pipeline().build(). " + "Pass the default-exported value from a pipeline definition file.");
|
|
16706
17148
|
}
|
|
16707
17149
|
return { _tag: "assign", pipeline: pipeline2 };
|
|
@@ -16789,7 +17231,7 @@ function serializeDefaultPipelineAssignment(spec) {
|
|
|
16789
17231
|
return serializeAssignmentRule(rule);
|
|
16790
17232
|
});
|
|
16791
17233
|
return {
|
|
16792
|
-
|
|
17234
|
+
pipelineDefinitionKey: primaryKey,
|
|
16793
17235
|
rulesJson: { rules: serializedRules },
|
|
16794
17236
|
defaultEventType: defaultType,
|
|
16795
17237
|
defaultEventParamsJson: defaultParams,
|
|
@@ -17087,6 +17529,8 @@ function checkHealthChecks(steps) {
|
|
|
17087
17529
|
return issues;
|
|
17088
17530
|
}
|
|
17089
17531
|
function routeTargets(policy) {
|
|
17532
|
+
if (!policy)
|
|
17533
|
+
return [];
|
|
17090
17534
|
const keys = [];
|
|
17091
17535
|
if (policy.defaultEventType === "route" && typeof policy.defaultEventParamsJson?.["pipelineKey"] === "string") {
|
|
17092
17536
|
keys.push(policy.defaultEventParamsJson["pipelineKey"]);
|
|
@@ -17105,36 +17549,42 @@ function checkRouteTargets(pipelines, knownPipelineKeys) {
|
|
|
17105
17549
|
...knownPipelineKeys
|
|
17106
17550
|
]);
|
|
17107
17551
|
for (const pipeline2 of pipelines) {
|
|
17108
|
-
for (const
|
|
17109
|
-
for (const target of routeTargets(
|
|
17552
|
+
for (const node of pipeline2.nodeDefinitions) {
|
|
17553
|
+
for (const target of routeTargets(node.advancementPolicyDefinition)) {
|
|
17110
17554
|
if (known.has(target))
|
|
17111
17555
|
continue;
|
|
17112
17556
|
issues.push({
|
|
17113
17557
|
check: "route-target",
|
|
17114
|
-
message: `Pipeline "${pipeline2.key}" step "${
|
|
17558
|
+
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
17559
|
});
|
|
17116
17560
|
}
|
|
17117
17561
|
}
|
|
17118
17562
|
}
|
|
17119
17563
|
return issues;
|
|
17120
17564
|
}
|
|
17121
|
-
function executionRanks(
|
|
17122
|
-
const
|
|
17123
|
-
const
|
|
17124
|
-
|
|
17125
|
-
|
|
17565
|
+
function executionRanks(nodeDefinitions, dependencyEdges) {
|
|
17566
|
+
const indexes = nodeDefinitions.map((_, index) => index);
|
|
17567
|
+
const orderedNodes = tryOrderChainNodeDefinitions(nodeDefinitions, dependencyEdges);
|
|
17568
|
+
if (orderedNodes === null) {
|
|
17569
|
+
return new Map(indexes.map((index, rank) => [index, rank]));
|
|
17570
|
+
}
|
|
17571
|
+
const indexByNodeKey = new Map(nodeDefinitions.map((node, index) => [node.nodeKey, index]));
|
|
17572
|
+
const ordered = orderedNodes.map((node) => indexByNodeKey.get(node.nodeKey) ?? 0);
|
|
17126
17573
|
return new Map(ordered.map((index, rank) => [index, rank]));
|
|
17127
17574
|
}
|
|
17128
17575
|
function bindingSource(binding) {
|
|
17129
17576
|
if (binding.source === "step_signal") {
|
|
17130
|
-
return { stepKey: binding.stepKey, signalKey: binding.signalKey };
|
|
17577
|
+
return { stepKey: binding.stepKey, signalKey: binding.signalKey, kind: "signal" };
|
|
17131
17578
|
}
|
|
17132
17579
|
if (binding.source === "step_output") {
|
|
17133
|
-
return { stepKey: binding.stepKey, signalKey: null };
|
|
17580
|
+
return { stepKey: binding.stepKey, signalKey: null, kind: "output" };
|
|
17581
|
+
}
|
|
17582
|
+
if (binding.source === "signals_list") {
|
|
17583
|
+
return { stepKey: binding.stepKey, signalKey: null, kind: "signals_list" };
|
|
17134
17584
|
}
|
|
17135
17585
|
return null;
|
|
17136
17586
|
}
|
|
17137
|
-
function declaredSignalKeys(stepKey, stepsByKey,
|
|
17587
|
+
function declaredSignalKeys(stepKey, stepsByKey, pipelineNodeDefinitions) {
|
|
17138
17588
|
const specs = stepsByKey.get(stepKey);
|
|
17139
17589
|
if (!specs || specs.length === 0)
|
|
17140
17590
|
return null;
|
|
@@ -17143,10 +17593,10 @@ function declaredSignalKeys(stepKey, stepsByKey, pipelineSteps) {
|
|
|
17143
17593
|
for (const signal2 of spec.signalExtractorDefinitions)
|
|
17144
17594
|
keys.add(signal2.key);
|
|
17145
17595
|
}
|
|
17146
|
-
for (const
|
|
17147
|
-
if (
|
|
17596
|
+
for (const node of pipelineNodeDefinitions) {
|
|
17597
|
+
if (node.stepKey !== stepKey)
|
|
17148
17598
|
continue;
|
|
17149
|
-
for (const computed of
|
|
17599
|
+
for (const computed of node.computedSignalDefinitions ?? [])
|
|
17150
17600
|
keys.add(computed.key);
|
|
17151
17601
|
}
|
|
17152
17602
|
return [...keys];
|
|
@@ -17154,18 +17604,18 @@ function declaredSignalKeys(stepKey, stepsByKey, pipelineSteps) {
|
|
|
17154
17604
|
function checkSignalBindings(pipelines, stepsByKey) {
|
|
17155
17605
|
const issues = [];
|
|
17156
17606
|
for (const pipeline2 of pipelines) {
|
|
17157
|
-
const ranks = executionRanks(pipeline2.
|
|
17158
|
-
const order = [...pipeline2.
|
|
17607
|
+
const ranks = executionRanks(pipeline2.nodeDefinitions, pipeline2.dependencyEdges);
|
|
17608
|
+
const order = [...pipeline2.nodeDefinitions.keys()].sort((left, right) => (ranks.get(left) ?? 0) - (ranks.get(right) ?? 0)).map((index) => pipeline2.nodeDefinitions[index]?.stepKey ?? "");
|
|
17159
17609
|
const orderHint = `Steps in "${pipeline2.key}", in order: ${order.join(" \u2192 ")}.`;
|
|
17160
|
-
pipeline2.
|
|
17610
|
+
pipeline2.nodeDefinitions.forEach((node, index) => {
|
|
17161
17611
|
const consumerRank = ranks.get(index) ?? index;
|
|
17162
|
-
const where = `Pipeline "${pipeline2.key}" step "${
|
|
17163
|
-
for (const [field, binding] of Object.entries(
|
|
17612
|
+
const where = `Pipeline "${pipeline2.key}" step "${node.stepKey ?? node.nodeKey}"`;
|
|
17613
|
+
for (const [field, binding] of Object.entries(node.inputBindingsJson ?? {})) {
|
|
17164
17614
|
const source = bindingSource(binding);
|
|
17165
17615
|
if (!source)
|
|
17166
17616
|
continue;
|
|
17167
|
-
const what = source.
|
|
17168
|
-
const producerRanks = pipeline2.
|
|
17617
|
+
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}"`;
|
|
17618
|
+
const producerRanks = pipeline2.nodeDefinitions.map((candidate, candidateIndex) => candidate.stepKey === source.stepKey ? ranks.get(candidateIndex) ?? candidateIndex : null).filter((rank) => rank !== null);
|
|
17169
17619
|
if (producerRanks.length === 0) {
|
|
17170
17620
|
issues.push({
|
|
17171
17621
|
check: "signal-binding",
|
|
@@ -17182,7 +17632,7 @@ function checkSignalBindings(pipelines, stepsByKey) {
|
|
|
17182
17632
|
}
|
|
17183
17633
|
if (source.signalKey === null)
|
|
17184
17634
|
continue;
|
|
17185
|
-
const available = declaredSignalKeys(source.stepKey, stepsByKey, pipeline2.
|
|
17635
|
+
const available = declaredSignalKeys(source.stepKey, stepsByKey, pipeline2.nodeDefinitions);
|
|
17186
17636
|
if (available === null || available.includes(source.signalKey))
|
|
17187
17637
|
continue;
|
|
17188
17638
|
issues.push({
|
|
@@ -17233,7 +17683,7 @@ function isPipelineDefinitionSpec(value) {
|
|
|
17233
17683
|
if (typeof value !== "object" || value === null)
|
|
17234
17684
|
return false;
|
|
17235
17685
|
const obj = value;
|
|
17236
|
-
return typeof obj["key"] === "string" && typeof obj["name"] === "string" && typeof obj["version"] === "number" && Array.isArray(obj["
|
|
17686
|
+
return typeof obj["key"] === "string" && typeof obj["name"] === "string" && typeof obj["version"] === "number" && Array.isArray(obj["nodeDefinitions"]);
|
|
17237
17687
|
}
|
|
17238
17688
|
async function importModule(path) {
|
|
17239
17689
|
return await import(pathToFileURL(path).href);
|
|
@@ -17331,7 +17781,7 @@ async function syncDefaultPipelineAssignment(spec, opts, headers, pipelinesClien
|
|
|
17331
17781
|
p.id
|
|
17332
17782
|
]));
|
|
17333
17783
|
const referencedKeys = new Set;
|
|
17334
|
-
referencedKeys.add(serialized.
|
|
17784
|
+
referencedKeys.add(serialized.pipelineDefinitionKey);
|
|
17335
17785
|
for (const rule of serialized.rulesJson.rules) {
|
|
17336
17786
|
if (rule.event.type === "assign" && typeof rule.event.params?.["pipelineKey"] === "string") {
|
|
17337
17787
|
referencedKeys.add(rule.event.params["pipelineKey"]);
|
|
@@ -17342,9 +17792,9 @@ async function syncDefaultPipelineAssignment(spec, opts, headers, pipelinesClien
|
|
|
17342
17792
|
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
17793
|
}
|
|
17344
17794
|
}
|
|
17345
|
-
const
|
|
17346
|
-
if (!
|
|
17347
|
-
throw new Error(`Pipeline key "${serialized.
|
|
17795
|
+
const pipelineDefinitionId = pipelineKeyToId.get(serialized.pipelineDefinitionKey);
|
|
17796
|
+
if (!pipelineDefinitionId) {
|
|
17797
|
+
throw new Error(`Pipeline key "${serialized.pipelineDefinitionKey}" was not found on the server.`);
|
|
17348
17798
|
}
|
|
17349
17799
|
const resolvedRules = serialized.rulesJson.rules.map((rule) => {
|
|
17350
17800
|
if (rule.event.type === "assign" && typeof rule.event.params?.["pipelineKey"] === "string") {
|
|
@@ -17373,7 +17823,7 @@ async function syncDefaultPipelineAssignment(spec, opts, headers, pipelinesClien
|
|
|
17373
17823
|
path: { projectId: opts.projectId },
|
|
17374
17824
|
body: {
|
|
17375
17825
|
defaultPipelineAssignment: {
|
|
17376
|
-
|
|
17826
|
+
pipelineDefinitionId,
|
|
17377
17827
|
rulesJson: { rules: resolvedRules },
|
|
17378
17828
|
defaultEventType: serialized.defaultEventType,
|
|
17379
17829
|
defaultEventParamsJson: serialized.defaultEventParamsJson,
|
|
@@ -17385,7 +17835,7 @@ async function syncDefaultPipelineAssignment(spec, opts, headers, pipelinesClien
|
|
|
17385
17835
|
if (result.error) {
|
|
17386
17836
|
throw new Error(`Failed to update project default pipeline assignment: ${JSON.stringify(result.error)}`);
|
|
17387
17837
|
}
|
|
17388
|
-
log(`\u2713 default pipeline assignment \u2192 synced (primary pipeline: ${serialized.
|
|
17838
|
+
log(`\u2713 default pipeline assignment \u2192 synced (primary pipeline: ${serialized.pipelineDefinitionKey})`);
|
|
17389
17839
|
return true;
|
|
17390
17840
|
}
|
|
17391
17841
|
export {
|