@workglow/task-graph 0.2.13 → 0.2.14

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.
Files changed (38) hide show
  1. package/dist/browser.js +190 -31
  2. package/dist/browser.js.map +19 -18
  3. package/dist/bun.js +190 -31
  4. package/dist/bun.js.map +19 -18
  5. package/dist/node.js +190 -31
  6. package/dist/node.js.map +19 -18
  7. package/dist/task/EntitlementEnforcer.d.ts +37 -4
  8. package/dist/task/EntitlementEnforcer.d.ts.map +1 -1
  9. package/dist/task/EntitlementPolicy.d.ts +10 -0
  10. package/dist/task/EntitlementPolicy.d.ts.map +1 -1
  11. package/dist/task/FallbackTask.d.ts +2 -1
  12. package/dist/task/FallbackTask.d.ts.map +1 -1
  13. package/dist/task/GraphAsTask.d.ts +8 -0
  14. package/dist/task/GraphAsTask.d.ts.map +1 -1
  15. package/dist/task/IteratorTask.d.ts +25 -6
  16. package/dist/task/IteratorTask.d.ts.map +1 -1
  17. package/dist/task/IteratorTaskRunner.d.ts +1 -1
  18. package/dist/task/IteratorTaskRunner.d.ts.map +1 -1
  19. package/dist/task/MapTask.d.ts +47 -3
  20. package/dist/task/MapTask.d.ts.map +1 -1
  21. package/dist/task/ReduceTask.d.ts +9 -3
  22. package/dist/task/ReduceTask.d.ts.map +1 -1
  23. package/dist/task/TaskJSON.d.ts +8 -1
  24. package/dist/task/TaskJSON.d.ts.map +1 -1
  25. package/dist/task/WhileTask.d.ts +20 -7
  26. package/dist/task/WhileTask.d.ts.map +1 -1
  27. package/dist/task-graph/ConditionalBuilder.d.ts +49 -0
  28. package/dist/task-graph/ConditionalBuilder.d.ts.map +1 -0
  29. package/dist/task-graph/Conversions.d.ts.map +1 -1
  30. package/dist/task-graph/GraphSchemaUtils.d.ts +2 -2
  31. package/dist/task-graph/GraphSchemaUtils.d.ts.map +1 -1
  32. package/dist/task-graph/GraphToWorkflowCode.d.ts.map +1 -1
  33. package/dist/task-graph/TaskGraph.d.ts +6 -0
  34. package/dist/task-graph/TaskGraph.d.ts.map +1 -1
  35. package/dist/task-graph/Workflow.d.ts +18 -1
  36. package/dist/task-graph/Workflow.d.ts.map +1 -1
  37. package/package.json +7 -7
  38. package/src/EXECUTION_MODEL.md +6 -0
package/dist/browser.js CHANGED
@@ -636,7 +636,8 @@ function computeGraphInputSchema(graph, options) {
636
636
  for (const [inputName, inputProp] of Object.entries(taskProperties)) {
637
637
  if (!properties[inputName]) {
638
638
  properties[inputName] = inputProp;
639
- if (taskInputSchema.required && taskInputSchema.required.includes(inputName)) {
639
+ const isRequired = taskInputSchema.required?.includes(inputName) === true && !(task.defaults && task.defaults[inputName] !== undefined);
640
+ if (isRequired) {
640
641
  required.push(inputName);
641
642
  }
642
643
  if (trackOrigins) {
@@ -949,6 +950,7 @@ import { DirectedAcyclicGraph } from "@workglow/util/graph";
949
950
 
950
951
  // src/task/GraphAsTask.ts
951
952
  import { getLogger as getLogger4 } from "@workglow/util";
953
+ import { CycleError } from "@workglow/util/graph";
952
954
  import { compileSchema as compileSchema2 } from "@workglow/util/schema";
953
955
 
954
956
  // src/task-graph/TaskGraphRunner.ts
@@ -2473,6 +2475,11 @@ function evaluatePolicy(policy, required) {
2473
2475
  }
2474
2476
  return results;
2475
2477
  }
2478
+ function can(policy, id, resources) {
2479
+ const required = resources !== undefined ? { id, resources } : { id };
2480
+ const [result] = evaluatePolicy(policy, { entitlements: [required] });
2481
+ return result;
2482
+ }
2476
2483
 
2477
2484
  // src/task/EntitlementResolver.ts
2478
2485
  import { createServiceToken as createServiceToken2 } from "@workglow/util";
@@ -2489,6 +2496,16 @@ var DENY_ALL_RESOLVER = {
2489
2496
  var ENTITLEMENT_RESOLVER = createServiceToken2("workglow.entitlementResolver");
2490
2497
 
2491
2498
  // src/task/EntitlementEnforcer.ts
2499
+ function formatEntitlementDenial(denial) {
2500
+ switch (denial.reason) {
2501
+ case "policy-deny":
2502
+ return `${denial.entitlement.id} (denied by rule ${denial.matchedRule.id})`;
2503
+ case "user-deny":
2504
+ return `${denial.entitlement.id} (denied by user)`;
2505
+ case "default-deny":
2506
+ return `${denial.entitlement.id} (no matching grant)`;
2507
+ }
2508
+ }
2492
2509
  var PERMISSIVE_ENFORCER = {
2493
2510
  checkAll: async () => [],
2494
2511
  checkTask: async () => []
@@ -2499,24 +2516,27 @@ function createPolicyEnforcer(policy, resolver = PERMISSIVE_RESOLVER) {
2499
2516
  const denied = [];
2500
2517
  for (const result of results) {
2501
2518
  if (result.verdict === "denied") {
2502
- denied.push(result.entitlement);
2519
+ if (result.matchedRule) {
2520
+ denied.push({ entitlement: result.entitlement, reason: "policy-deny", matchedRule: result.matchedRule });
2521
+ } else {
2522
+ denied.push({ entitlement: result.entitlement, reason: "default-deny" });
2523
+ }
2503
2524
  } else if (result.verdict === "ask") {
2504
2525
  const request = {
2505
2526
  entitlement: result.entitlement,
2506
2527
  taskType: taskType ?? "unknown",
2507
2528
  taskId: taskId ?? "unknown"
2508
2529
  };
2509
- const saved = resolver.lookup(request);
2510
- if (saved !== undefined) {
2511
- if (saved === "deny") {
2512
- denied.push(result.entitlement);
2513
- }
2514
- continue;
2530
+ let answer = resolver.lookup(request);
2531
+ if (answer === undefined) {
2532
+ answer = await resolver.prompt(request);
2533
+ resolver.save(request, answer);
2515
2534
  }
2516
- const answer = await resolver.prompt(request);
2517
- resolver.save(request, answer);
2518
2535
  if (answer === "deny") {
2519
- denied.push(result.entitlement);
2536
+ if (!result.matchedRule) {
2537
+ throw new Error(`Invariant violation: ask verdict for "${result.entitlement.id}" is missing matchedRule`);
2538
+ }
2539
+ denied.push({ entitlement: result.entitlement, reason: "user-deny", matchedRule: result.matchedRule });
2520
2540
  }
2521
2541
  }
2522
2542
  }
@@ -3024,7 +3044,7 @@ class TaskGraphRunner {
3024
3044
  if (this.activeEnforcer && task.constructor.hasDynamicEntitlements) {
3025
3045
  const denied = await this.activeEnforcer.checkTask(task);
3026
3046
  if (denied.length > 0) {
3027
- throw new TaskEntitlementError(`Task ${task.constructor.type} denied entitlements: ${denied.map((e) => e.id).join(", ")}`);
3047
+ throw new TaskEntitlementError(`Task ${task.constructor.type} denied entitlements: ${denied.map(formatEntitlementDenial).join(", ")}`);
3028
3048
  }
3029
3049
  }
3030
3050
  if (isStreamable) {
@@ -3247,7 +3267,7 @@ class TaskGraphRunner {
3247
3267
  const enforcer = this.registry.get(ENTITLEMENT_ENFORCER);
3248
3268
  const denied = await enforcer.checkAll(computeGraphEntitlements(this.graph));
3249
3269
  if (denied.length > 0) {
3250
- throw new TaskEntitlementError(`Denied entitlements: ${denied.map((e) => e.id).join(", ")}`);
3270
+ throw new TaskEntitlementError(`Denied entitlements: ${denied.map(formatEntitlementDenial).join(", ")}`);
3251
3271
  }
3252
3272
  this.activeEnforcer = enforcer;
3253
3273
  } else {
@@ -3591,6 +3611,18 @@ class GraphAsTask extends Task {
3591
3611
  yield { type: "finish", data: input };
3592
3612
  }
3593
3613
  }
3614
+ validateAcyclic() {
3615
+ if (!this.hasChildren())
3616
+ return;
3617
+ if (!this.subGraph.isAcyclic()) {
3618
+ throw new CycleError(`${this.type} (${this.id}): subgraph contains a cycle — loop tasks must wrap an acyclic subgraph.`);
3619
+ }
3620
+ for (const child of this.subGraph.getTasks()) {
3621
+ if (child instanceof GraphAsTask) {
3622
+ child.validateAcyclic();
3623
+ }
3624
+ }
3625
+ }
3594
3626
  regenerateGraph() {
3595
3627
  this._inputSchemaNode = undefined;
3596
3628
  this.events.emit("regenerate");
@@ -3741,7 +3773,7 @@ function convertPipeFunctionToTask(fn, config) {
3741
3773
  properties: {
3742
3774
  [DATAFLOW_ALL_PORTS]: {}
3743
3775
  },
3744
- additionalProperties: false
3776
+ additionalProperties: true
3745
3777
  };
3746
3778
  };
3747
3779
  static outputSchema = () => {
@@ -3750,7 +3782,7 @@ function convertPipeFunctionToTask(fn, config) {
3750
3782
  properties: {
3751
3783
  [DATAFLOW_ALL_PORTS]: {}
3752
3784
  },
3753
- additionalProperties: false
3785
+ additionalProperties: true
3754
3786
  };
3755
3787
  };
3756
3788
  static cacheable = false;
@@ -3859,6 +3891,9 @@ class TaskGraph {
3859
3891
  topologicallySortedNodes() {
3860
3892
  return this._dag.topologicallySortedNodes();
3861
3893
  }
3894
+ isAcyclic() {
3895
+ return this._dag.isAcyclic();
3896
+ }
3862
3897
  addTask(task, config) {
3863
3898
  return this._dag.addNode(ensureTask(task, config));
3864
3899
  }
@@ -4132,7 +4167,75 @@ function serialGraph(tasks, inputHandle, outputHandle) {
4132
4167
  return graph;
4133
4168
  }
4134
4169
  // src/task-graph/Workflow.ts
4135
- import { EventEmitter as EventEmitter5, getLogger as getLogger5, uuid4 as uuid45 } from "@workglow/util";
4170
+ import { EventEmitter as EventEmitter5, getLogger as getLogger5, uuid4 as uuid46 } from "@workglow/util";
4171
+
4172
+ // src/task-graph/ConditionalBuilder.ts
4173
+ import { uuid4 as uuid45 } from "@workglow/util";
4174
+ class ConditionalBuilder {
4175
+ workflow;
4176
+ condition;
4177
+ thenSpec;
4178
+ elseSpec;
4179
+ constructor(workflow, condition) {
4180
+ this.workflow = workflow;
4181
+ this.condition = condition;
4182
+ }
4183
+ then(taskClass, input, config) {
4184
+ this.thenSpec = { taskClass, input, config };
4185
+ return this;
4186
+ }
4187
+ else(taskClass, input, config) {
4188
+ this.elseSpec = { taskClass, input, config };
4189
+ return this;
4190
+ }
4191
+ endIf() {
4192
+ if (!this.thenSpec) {
4193
+ throw new WorkflowError(".endIf() called without a prior .then(...) call");
4194
+ }
4195
+ const thenPort = "then";
4196
+ const elsePort = "else";
4197
+ const branches = [
4198
+ {
4199
+ id: thenPort,
4200
+ condition: this.condition,
4201
+ outputPort: thenPort
4202
+ }
4203
+ ];
4204
+ if (this.elseSpec) {
4205
+ branches.push({
4206
+ id: elsePort,
4207
+ condition: (input) => !this.condition(input),
4208
+ outputPort: elsePort
4209
+ });
4210
+ }
4211
+ const conditionalTask = new ConditionalTask({
4212
+ id: uuid45(),
4213
+ branches,
4214
+ exclusive: true,
4215
+ defaultBranch: this.elseSpec ? elsePort : undefined
4216
+ });
4217
+ this.workflow.graph.addTask(conditionalTask);
4218
+ const thenTask = instantiate(this.thenSpec);
4219
+ this.workflow.graph.addTask(thenTask);
4220
+ this.workflow.graph.addDataflow(new Dataflow(conditionalTask.id, thenPort, thenTask.id, "*"));
4221
+ if (this.elseSpec) {
4222
+ const elseTask = instantiate(this.elseSpec);
4223
+ this.workflow.graph.addTask(elseTask);
4224
+ this.workflow.graph.addDataflow(new Dataflow(conditionalTask.id, elsePort, elseTask.id, "*"));
4225
+ }
4226
+ return this.workflow;
4227
+ }
4228
+ }
4229
+ function instantiate(spec) {
4230
+ const config = {
4231
+ id: uuid45(),
4232
+ ...spec.config,
4233
+ defaults: spec.input
4234
+ };
4235
+ return new spec.taskClass(config);
4236
+ }
4237
+
4238
+ // src/task-graph/Workflow.ts
4136
4239
  function getLastTask(workflow) {
4137
4240
  const tasks = workflow.graph.getTasks();
4138
4241
  return tasks.length > 0 ? tasks[tasks.length - 1] : undefined;
@@ -4275,7 +4378,7 @@ class Workflow {
4275
4378
  this._error = "";
4276
4379
  const parent = getLastTask(this);
4277
4380
  const task = this.addTaskToGraph(taskClass, {
4278
- id: uuid45(),
4381
+ id: uuid46(),
4279
4382
  ...config,
4280
4383
  defaults: input
4281
4384
  });
@@ -4556,7 +4659,7 @@ class Workflow {
4556
4659
  addLoopTask(taskClass, config = {}) {
4557
4660
  this._error = "";
4558
4661
  const parent = getLastTask(this);
4559
- const task = this.addTaskToGraph(taskClass, { id: uuid45(), ...config });
4662
+ const task = this.addTaskToGraph(taskClass, { id: uuid46(), ...config });
4560
4663
  if (this._dataFlows.length > 0) {
4561
4664
  this._dataFlows.forEach((dataflow) => {
4562
4665
  const taskSchema = task.inputSchema();
@@ -4576,6 +4679,9 @@ class Workflow {
4576
4679
  }
4577
4680
  return loopBuilder;
4578
4681
  }
4682
+ if(condition) {
4683
+ return new ConditionalBuilder(this, condition);
4684
+ }
4579
4685
  autoConnectLoopTask(pending) {
4580
4686
  if (!pending)
4581
4687
  return;
@@ -4933,6 +5039,7 @@ class Workflow {
4933
5039
  return;
4934
5040
  }
4935
5041
  this._iteratorTask.subGraph = this.graph;
5042
+ this._iteratorTask.validateAcyclic();
4936
5043
  }
4937
5044
  finalizeAndReturn() {
4938
5045
  if (!this._parentWorkflow) {
@@ -4967,6 +5074,7 @@ function getMethodNameMap() {
4967
5074
  }
4968
5075
  var LOOP_TASK_TYPES = {
4969
5076
  MapTask: { method: "map", endMethod: "endMap" },
5077
+ ForEachTask: { method: "forEach", endMethod: "endForEach" },
4970
5078
  ReduceTask: { method: "reduce", endMethod: "endReduce" },
4971
5079
  WhileTask: { method: "while", endMethod: "endWhile" },
4972
5080
  GraphAsTask: { method: "group", endMethod: "endGroup" }
@@ -5149,7 +5257,8 @@ function extractLoopConfig(task) {
5149
5257
  }
5150
5258
  break;
5151
5259
  }
5152
- case "MapTask": {
5260
+ case "MapTask":
5261
+ case "ForEachTask": {
5153
5262
  if (rawConfig.preserveOrder !== undefined && rawConfig.preserveOrder !== true) {
5154
5263
  config.preserveOrder = rawConfig.preserveOrder;
5155
5264
  }
@@ -5162,16 +5271,22 @@ function extractLoopConfig(task) {
5162
5271
  if (rawConfig.batchSize !== undefined) {
5163
5272
  config.batchSize = rawConfig.batchSize;
5164
5273
  }
5274
+ if (rawConfig.maxIterations !== undefined) {
5275
+ config.maxIterations = rawConfig.maxIterations;
5276
+ }
5165
5277
  break;
5166
5278
  }
5167
5279
  case "ReduceTask": {
5168
5280
  if (rawConfig.initialValue !== undefined) {
5169
5281
  config.initialValue = rawConfig.initialValue;
5170
5282
  }
5283
+ if (rawConfig.maxIterations !== undefined) {
5284
+ config.maxIterations = rawConfig.maxIterations;
5285
+ }
5171
5286
  break;
5172
5287
  }
5173
5288
  case "WhileTask": {
5174
- if (rawConfig.maxIterations !== undefined && rawConfig.maxIterations !== 100) {
5289
+ if (rawConfig.maxIterations !== undefined) {
5175
5290
  config.maxIterations = rawConfig.maxIterations;
5176
5291
  }
5177
5292
  if (rawConfig.chainIterations !== undefined && rawConfig.chainIterations !== true) {
@@ -5609,15 +5724,15 @@ async function compactSchemaInputs(input, schema, config, visited = new Set) {
5609
5724
  return compacted;
5610
5725
  }
5611
5726
  // src/task/IteratorTaskRunner.ts
5612
- import { uuid4 as uuid46 } from "@workglow/util";
5727
+ import { uuid4 as uuid47 } from "@workglow/util";
5613
5728
  class IteratorTaskRunner extends GraphAsTaskRunner {
5614
5729
  aggregatingParentMapProgress = false;
5615
5730
  mapPartialProgress = [];
5616
5731
  mapPartialIterationCount = 0;
5617
5732
  async executeTask(input) {
5618
5733
  let analysis = this.task.analyzeIterationInput(input);
5619
- const maxIterations = this.task.config.maxIterations;
5620
- if (maxIterations !== undefined && maxIterations > 0 && analysis.iterationCount > maxIterations) {
5734
+ const maxIterations = resolveIterationBound(this.task.config.maxIterations);
5735
+ if (analysis.iterationCount > maxIterations) {
5621
5736
  analysis = { ...analysis, iterationCount: maxIterations };
5622
5737
  }
5623
5738
  if (analysis.iterationCount === 0) {
@@ -5723,7 +5838,7 @@ class IteratorTaskRunner extends GraphAsTaskRunner {
5723
5838
  const idMap = new Map;
5724
5839
  for (const task of graph.getTasks()) {
5725
5840
  const ctor = task.constructor;
5726
- const newId = uuid46();
5841
+ const newId = uuid47();
5727
5842
  idMap.set(task.config.id, newId);
5728
5843
  const clonedConfig = { ...task.config, id: newId };
5729
5844
  const newTask = new ctor({ ...clonedConfig, defaults: task.defaults }, task.runConfig);
@@ -5793,15 +5908,21 @@ var ITERATOR_CONTEXT_SCHEMA = {
5793
5908
  }
5794
5909
  }
5795
5910
  };
5911
+ function resolveIterationBound(bound) {
5912
+ return bound === "unbounded" ? Number.POSITIVE_INFINITY : bound;
5913
+ }
5796
5914
  var iteratorTaskConfigSchema = {
5797
5915
  type: "object",
5798
5916
  properties: {
5799
5917
  ...graphAsTaskConfigSchema["properties"],
5800
5918
  concurrencyLimit: { type: "integer", minimum: 1 },
5801
5919
  batchSize: { type: "integer", minimum: 1 },
5802
- maxIterations: { type: "integer", minimum: 1 },
5920
+ maxIterations: {
5921
+ oneOf: [{ type: "integer", minimum: 1 }, { type: "string", const: "unbounded" }]
5922
+ },
5803
5923
  iterationInputConfig: { type: "object", additionalProperties: true }
5804
5924
  },
5925
+ required: ["maxIterations"],
5805
5926
  additionalProperties: false
5806
5927
  };
5807
5928
  function isArrayVariant(schema) {
@@ -5916,6 +6037,12 @@ class IteratorTask extends GraphAsTask {
5916
6037
  static configSchema() {
5917
6038
  return iteratorTaskConfigSchema;
5918
6039
  }
6040
+ constructor(config = {}, runConfig = {}) {
6041
+ if (config.maxIterations === undefined) {
6042
+ throw new TaskConfigurationError(`${new.target.type ?? "IteratorTask"}: maxIterations is required. ` + `Pass a positive integer to cap iteration, or "unbounded" to opt out explicitly.`);
6043
+ }
6044
+ super(config, runConfig);
6045
+ }
5919
6046
  static getIterationContextSchema() {
5920
6047
  return ITERATOR_CONTEXT_SCHEMA;
5921
6048
  }
@@ -6305,13 +6432,16 @@ var whileTaskConfigSchema = {
6305
6432
  properties: {
6306
6433
  ...graphAsTaskConfigSchema["properties"],
6307
6434
  condition: {},
6308
- maxIterations: { type: "integer", minimum: 1 },
6435
+ maxIterations: {
6436
+ oneOf: [{ type: "integer", minimum: 1 }, { type: "string", const: "unbounded" }]
6437
+ },
6309
6438
  chainIterations: { type: "boolean" },
6310
6439
  conditionField: { type: "string" },
6311
6440
  conditionOperator: { type: "string" },
6312
6441
  conditionValue: { type: "string" },
6313
6442
  iterationInputConfig: { type: "object", additionalProperties: true }
6314
6443
  },
6444
+ required: ["maxIterations"],
6315
6445
  additionalProperties: false
6316
6446
  };
6317
6447
 
@@ -6324,6 +6454,12 @@ class WhileTask extends GraphAsTask {
6324
6454
  static configSchema() {
6325
6455
  return whileTaskConfigSchema;
6326
6456
  }
6457
+ constructor(config = {}, runConfig = {}) {
6458
+ if (config.maxIterations === undefined) {
6459
+ throw new TaskConfigurationError(`${new.target.type ?? "WhileTask"}: maxIterations is required. ` + `Pass a positive integer to cap iteration, or "unbounded" to opt out explicitly.`);
6460
+ }
6461
+ super(config, runConfig);
6462
+ }
6327
6463
  static getIterationContextSchema() {
6328
6464
  return WHILE_CONTEXT_SCHEMA;
6329
6465
  }
@@ -6341,7 +6477,7 @@ class WhileTask extends GraphAsTask {
6341
6477
  return this.config.condition;
6342
6478
  }
6343
6479
  get maxIterations() {
6344
- return this.config.maxIterations ?? 100;
6480
+ return resolveIterationBound(this.config.maxIterations);
6345
6481
  }
6346
6482
  get chainIterations() {
6347
6483
  return this.config.chainIterations ?? true;
@@ -6948,8 +7084,10 @@ var mapTaskConfigSchema = {
6948
7084
  properties: {
6949
7085
  ...iteratorTaskConfigSchema["properties"],
6950
7086
  preserveOrder: { type: "boolean" },
6951
- flatten: { type: "boolean" }
7087
+ flatten: { type: "boolean" },
7088
+ discardResults: { type: "boolean" }
6952
7089
  },
7090
+ required: iteratorTaskConfigSchema.required,
6953
7091
  additionalProperties: false
6954
7092
  };
6955
7093
 
@@ -6982,6 +7120,9 @@ class MapTask extends IteratorTask {
6982
7120
  get flatten() {
6983
7121
  return this.config.flatten ?? false;
6984
7122
  }
7123
+ get discardResults() {
7124
+ return this.config.discardResults ?? false;
7125
+ }
6985
7126
  preserveIterationOrder() {
6986
7127
  return this.preserveOrder;
6987
7128
  }
@@ -7003,6 +7144,9 @@ class MapTask extends IteratorTask {
7003
7144
  return this.getWrappedOutputSchema();
7004
7145
  }
7005
7146
  collectResults(results) {
7147
+ if (this.discardResults) {
7148
+ return this.getEmptyResult();
7149
+ }
7006
7150
  const collected = super.collectResults(results);
7007
7151
  if (!this.flatten || typeof collected !== "object" || collected === null) {
7008
7152
  return collected;
@@ -7018,8 +7162,19 @@ class MapTask extends IteratorTask {
7018
7162
  return flattened;
7019
7163
  }
7020
7164
  }
7165
+
7166
+ class ForEachTask extends MapTask {
7167
+ static type = "ForEachTask";
7168
+ static title = "For Each";
7169
+ static description = "Runs a workflow per array item for side effects; discards collected results";
7170
+ constructor(config = {}, runConfig = {}) {
7171
+ super({ discardResults: true, ...config }, runConfig);
7172
+ }
7173
+ }
7021
7174
  Workflow.prototype.map = CreateLoopWorkflow(MapTask);
7022
7175
  Workflow.prototype.endMap = CreateEndLoopWorkflow("endMap");
7176
+ Workflow.prototype.forEach = CreateLoopWorkflow(ForEachTask);
7177
+ Workflow.prototype.endForEach = CreateEndLoopWorkflow("endForEach");
7023
7178
  // src/task/ReduceTask.ts
7024
7179
  var reduceTaskConfigSchema = {
7025
7180
  type: "object",
@@ -7038,13 +7193,13 @@ class ReduceTask extends IteratorTask {
7038
7193
  static configSchema() {
7039
7194
  return reduceTaskConfigSchema;
7040
7195
  }
7041
- constructor(config = {}) {
7196
+ constructor(config = {}, runConfig = {}) {
7042
7197
  const reduceConfig = {
7043
7198
  ...config,
7044
7199
  concurrencyLimit: 1,
7045
7200
  batchSize: 1
7046
7201
  };
7047
- super(reduceConfig);
7202
+ super(reduceConfig, runConfig);
7048
7203
  }
7049
7204
  get initialValue() {
7050
7205
  return this.config.initialValue ?? {};
@@ -8123,6 +8278,7 @@ export {
8123
8278
  scanGraphForCredentials,
8124
8279
  resourcePatternMatches,
8125
8280
  resolveSchemaInputs,
8281
+ resolveIterationBound,
8126
8282
  resetMethodNameCache,
8127
8283
  removeIterationProperties,
8128
8284
  registerJobQueueFactory,
@@ -8167,6 +8323,7 @@ export {
8167
8323
  getFormatPrefix,
8168
8324
  getAppendPortId,
8169
8325
  formatValue,
8326
+ formatEntitlementDenial,
8170
8327
  findArrayPorts,
8171
8328
  filterIterationProperties,
8172
8329
  fallbackTaskConfigSchema,
@@ -8195,6 +8352,7 @@ export {
8195
8352
  computeGraphInputSchema,
8196
8353
  computeGraphEntitlements,
8197
8354
  compactSchemaInputs,
8355
+ can,
8198
8356
  calculateNodeDepths,
8199
8357
  buildIterationInputSchema,
8200
8358
  addIterationContextToSchema,
@@ -8247,6 +8405,7 @@ export {
8247
8405
  GraphAsTaskRunner,
8248
8406
  GraphAsTask,
8249
8407
  GRAPH_RESULT_ARRAY,
8408
+ ForEachTask,
8250
8409
  FallbackTaskRunner,
8251
8410
  FallbackTask,
8252
8411
  EventTaskGraphToDagMapping,
@@ -8270,4 +8429,4 @@ export {
8270
8429
  BROWSER_GRANTS
8271
8430
  };
8272
8431
 
8273
- //# debugId=A2F9041FD815B90264756E2164756E21
8432
+ //# debugId=8CB4AA21F9A0895064756E2164756E21