From 978109d3fc73495b08fa6bffbeedb4ea35c0e318 Mon Sep 17 00:00:00 2001 From: Sienna Meridian Satterwhite Date: Sun, 5 Apr 2026 11:52:40 +0100 Subject: [PATCH] feat(wfe-core): add step config API for attaching runtime JSON config Adds StepBuilder::config() to attach arbitrary JSON configuration to individual steps, readable at runtime via context.step.step_config. Bumps version to 1.6.1. --- Cargo.toml | 2 +- wfe-core/src/builder/step_builder.rs | 8 +++++ wfe-core/src/builder/workflow_builder.rs | 45 ++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index f0215b2..fa87cd0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ members = ["wfe-core", "wfe-sqlite", "wfe-postgres", "wfe-opensearch", "wfe-valk resolver = "2" [workspace.package] -version = "1.6.0" +version = "1.6.1" edition = "2024" license = "MIT" repository = "https://src.sunbeam.pt/studio/wfe" diff --git a/wfe-core/src/builder/step_builder.rs b/wfe-core/src/builder/step_builder.rs index 7c90502..01fc695 100644 --- a/wfe-core/src/builder/step_builder.rs +++ b/wfe-core/src/builder/step_builder.rs @@ -43,6 +43,14 @@ impl StepBuilder { self } + /// Attach arbitrary JSON configuration to this step. + /// + /// The step can read it at runtime via `context.step.step_config`. + pub fn config(mut self, config: serde_json::Value) -> Self { + self.builder.steps[self.step_id].step_config = Some(config); + self + } + /// Add a compensation step for saga rollback. pub fn compensate_with(mut self) -> Self { let comp_id = self.builder.add_step(std::any::type_name::()); diff --git a/wfe-core/src/builder/workflow_builder.rs b/wfe-core/src/builder/workflow_builder.rs index d67128b..bd7f548 100644 --- a/wfe-core/src/builder/workflow_builder.rs +++ b/wfe-core/src/builder/workflow_builder.rs @@ -341,6 +341,51 @@ mod tests { assert!(def.steps[1].step_type.contains("StepB")); } + #[test] + fn config_sets_step_config() { + let cfg = serde_json::json!({"namespace": "ory", "timeout": 30}); + let def = WorkflowBuilder::::new() + .start_with::() + .config(cfg.clone()) + .end_workflow() + .build("test", 1); + assert_eq!(def.steps[0].step_config, Some(cfg)); + } + + #[test] + fn config_chains_with_name() { + let cfg = serde_json::json!({"namespace": "data"}); + let def = WorkflowBuilder::::new() + .start_with::() + .name("apply-data") + .config(cfg.clone()) + .then::() + .end_workflow() + .build("test", 1); + assert_eq!(def.steps[0].name, Some("apply-data".into())); + assert_eq!(def.steps[0].step_config, Some(cfg)); + assert_eq!(def.steps[0].outcomes[0].next_step, 1); + } + + #[test] + fn config_on_multiple_steps_of_same_type() { + let cfg_a = serde_json::json!({"namespace": "ory"}); + let cfg_b = serde_json::json!({"namespace": "data"}); + let def = WorkflowBuilder::::new() + .start_with::() + .name("apply-ory") + .config(cfg_a.clone()) + .then::() + .name("apply-data") + .config(cfg_b.clone()) + .end_workflow() + .build("test", 1); + assert_eq!(def.steps[0].step_config, Some(cfg_a)); + assert_eq!(def.steps[1].step_config, Some(cfg_b)); + // Both are StepA + assert_eq!(def.steps[0].step_type, def.steps[1].step_type); + } + #[test] fn inline_step_via_then_fn() { let def = WorkflowBuilder::::new()