@doclo/flows 0.1.9 → 0.1.11

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/index.d.ts CHANGED
@@ -501,9 +501,12 @@ type SerializableConditionalStep = {
501
501
  branches: Record<string, SerializableFlow | FlowReference>;
502
502
  };
503
503
  /**
504
- * ForEach step (split + item flow)
504
+ * ForEach step (split + item flow OR branches by category)
505
+ *
506
+ * Two modes:
507
+ * 1. itemFlow: Single flow applied to ALL split items (original behavior)
508
+ * 2. branches: Different flows per category, items routed by split's `type` field
505
509
  *
506
- * itemFlow can be either an inline flow or a reference to a separate flow.
507
510
  * Use references to avoid hitting database JSON nesting limits.
508
511
  */
509
512
  type SerializableForEachStep = {
@@ -512,7 +515,15 @@ type SerializableForEachStep = {
512
515
  name?: string;
513
516
  nodeType: 'split';
514
517
  config: SplitConfig;
515
- itemFlow: SerializableFlow | FlowReference;
518
+ /**
519
+ * Single flow for all items (original forEach behavior)
520
+ */
521
+ itemFlow?: SerializableFlow | FlowReference;
522
+ /**
523
+ * Category-based branches: items routed by their `type` field from split.
524
+ * Keys must match the categories defined in splitConfig.categories.
525
+ */
526
+ branches?: Record<string, SerializableFlow | FlowReference>;
516
527
  };
517
528
  /**
518
529
  * Route branch configuration
@@ -823,11 +834,22 @@ interface ConditionalCompositeConfig {
823
834
  declare function createConditionalCompositeNode(config: ConditionalCompositeConfig): NodeDef<FlowInput, unknown>;
824
835
  /**
825
836
  * Configuration for forEach composite node
837
+ *
838
+ * Two modes:
839
+ * 1. itemFlow: Single flow applied to ALL split items
840
+ * 2. branches: Different flows per category, items routed by split's `type` field
826
841
  */
827
842
  interface ForEachCompositeConfig {
828
843
  stepId: string;
829
844
  splitConfig: SplitConfig;
830
- itemFlow: SerializableFlow | FlowReference;
845
+ /**
846
+ * Single flow for all items (original forEach behavior)
847
+ */
848
+ itemFlow?: SerializableFlow | FlowReference;
849
+ /**
850
+ * Category-based branches: items routed by their `type` field from split
851
+ */
852
+ branches?: Record<string, SerializableFlow | FlowReference>;
831
853
  providers: ProviderRegistry;
832
854
  flows: FlowRegistry;
833
855
  }
package/dist/index.js CHANGED
@@ -1467,7 +1467,10 @@ function createConditionalCompositeNode(config) {
1467
1467
  };
1468
1468
  }
1469
1469
  function createForEachCompositeNode(config) {
1470
- const { stepId, splitConfig, itemFlow, providers, flows } = config;
1470
+ const { stepId, splitConfig, itemFlow, branches, providers, flows } = config;
1471
+ if (!itemFlow && !branches) {
1472
+ throw new Error("ForEach composite requires either itemFlow or branches");
1473
+ }
1471
1474
  return {
1472
1475
  key: "forEach-composite",
1473
1476
  run: async (input, ctx) => {
@@ -1503,12 +1506,24 @@ function createForEachCompositeNode(config) {
1503
1506
  ctx.emit(`${stepId}:itemCount`, items.length);
1504
1507
  }
1505
1508
  phase = "forEach";
1506
- const itemFlowDef = resolveBranchFlow(itemFlow, flows);
1507
1509
  const itemFlowResults = [];
1508
1510
  const results = await Promise.allSettled(
1509
1511
  items.map(async (item, index) => {
1512
+ let targetFlowDef;
1513
+ if (branches) {
1514
+ const itemCategory = item.type;
1515
+ const branchFlow = branches[itemCategory] ?? branches["other"];
1516
+ if (!branchFlow) {
1517
+ throw new Error(
1518
+ `No branch found for category "${itemCategory}" and no "other" branch defined. Available branches: ${Object.keys(branches).join(", ")}`
1519
+ );
1520
+ }
1521
+ targetFlowDef = resolveBranchFlow(branchFlow, flows);
1522
+ } else {
1523
+ targetFlowDef = resolveBranchFlow(itemFlow, flows);
1524
+ }
1510
1525
  const flow = buildFlowFromConfig(
1511
- itemFlowDef,
1526
+ targetFlowDef,
1512
1527
  providers,
1513
1528
  flows,
1514
1529
  ctx?.observability?.config ? {
@@ -1518,6 +1533,7 @@ function createForEachCompositeNode(config) {
1518
1533
  parentNode: stepId,
1519
1534
  phase: "forEach",
1520
1535
  itemIndex: index,
1536
+ itemCategory: item.type,
1521
1537
  totalItems: items.length
1522
1538
  }
1523
1539
  } : void 0
@@ -1941,6 +1957,7 @@ function buildFlowFromConfig(flowDef, providers, flows, options) {
1941
1957
  stepId: step.id,
1942
1958
  splitConfig: step.config,
1943
1959
  itemFlow: step.itemFlow,
1960
+ branches: step.branches,
1944
1961
  providers,
1945
1962
  flows: flows || {}
1946
1963
  });