diff --git a/.changeset/metal-cycles-slide.md b/.changeset/metal-cycles-slide.md new file mode 100644 index 000000000..d6e090e78 --- /dev/null +++ b/.changeset/metal-cycles-slide.md @@ -0,0 +1,5 @@ +--- +"@workflow/swc-plugin": patch +--- + +Apply SWC transformation on step functions returned from factory function diff --git a/packages/swc-plugin-workflow/transform/src/lib.rs b/packages/swc-plugin-workflow/transform/src/lib.rs index 6aa01acc0..134c02289 100644 --- a/packages/swc-plugin-workflow/transform/src/lib.rs +++ b/packages/swc-plugin-workflow/transform/src/lib.rs @@ -858,7 +858,40 @@ impl StepTransform { stmt.visit_mut_children_with(self); } } - Stmt::Decl(Decl::Var(_)) => { + Stmt::Decl(Decl::Var(var_decl)) => { + // Check if any declarators contain arrow functions with object literal bodies + for declarator in &mut var_decl.decls { + if let Some(init) = &mut declarator.init { + if let Pat::Ident(binding) = &declarator.name { + let name = binding.id.sym.to_string(); + + // Check if the initializer is an arrow function with object literal body + if let Expr::Arrow(arrow_expr) = &mut **init { + match &mut *arrow_expr.body { + BlockStmtOrExpr::Expr(expr) => { + // Handle both direct object literals and parenthesized ones + let obj_lit_mut = match &mut **expr { + Expr::Object(obj) => Some(obj), + Expr::Paren(paren) => { + if let Expr::Object(obj) = &mut *paren.expr { + Some(obj) + } else { + None + } + } + _ => None, + }; + + if let Some(obj_lit) = obj_lit_mut { + self.process_object_properties_for_step_functions(obj_lit, &name); + } + } + _ => {} + } + } + } + } + } stmt.visit_mut_children_with(self); } _ => { diff --git a/packages/swc-plugin-workflow/transform/tests/fixture/factory-with-step-method/input.js b/packages/swc-plugin-workflow/transform/tests/fixture/factory-with-step-method/input.js new file mode 100644 index 000000000..6032e01ea --- /dev/null +++ b/packages/swc-plugin-workflow/transform/tests/fixture/factory-with-step-method/input.js @@ -0,0 +1,11 @@ +import fs from 'fs/promises'; + +const myFactory = () => ({ + myStep: async () => { + 'use step'; + await fs.mkdir('test'); + }, +}); + +export default myFactory; + diff --git a/packages/swc-plugin-workflow/transform/tests/fixture/factory-with-step-method/output-client.js b/packages/swc-plugin-workflow/transform/tests/fixture/factory-with-step-method/output-client.js new file mode 100644 index 000000000..9bbd17614 --- /dev/null +++ b/packages/swc-plugin-workflow/transform/tests/fixture/factory-with-step-method/output-client.js @@ -0,0 +1,7 @@ +import fs from 'fs/promises'; +const myFactory = ()=>({ + myStep: async ()=>{ + await fs.mkdir('test'); + } + }); +export default myFactory; diff --git a/packages/swc-plugin-workflow/transform/tests/fixture/factory-with-step-method/output-step.js b/packages/swc-plugin-workflow/transform/tests/fixture/factory-with-step-method/output-step.js new file mode 100644 index 000000000..f80c440c8 --- /dev/null +++ b/packages/swc-plugin-workflow/transform/tests/fixture/factory-with-step-method/output-step.js @@ -0,0 +1,11 @@ +import { registerStepFunction } from "workflow/internal/private"; +import fs from 'fs/promises'; +/**__internal_workflows{"steps":{"input.js":{"myFactory/myStep":{"stepId":"step//input.js//myFactory/myStep"}}}}*/; +var myFactory$myStep = async ()=>{ + await fs.mkdir('test'); +}; +const myFactory = ()=>({ + myStep: myFactory$myStep + }); +export default myFactory; +registerStepFunction("step//input.js//myFactory/myStep", myFactory$myStep); diff --git a/packages/swc-plugin-workflow/transform/tests/fixture/factory-with-step-method/output-workflow.js b/packages/swc-plugin-workflow/transform/tests/fixture/factory-with-step-method/output-workflow.js new file mode 100644 index 000000000..08caf239b --- /dev/null +++ b/packages/swc-plugin-workflow/transform/tests/fixture/factory-with-step-method/output-workflow.js @@ -0,0 +1,5 @@ +/**__internal_workflows{"steps":{"input.js":{"myFactory/myStep":{"stepId":"step//input.js//myFactory/myStep"}}}}*/; +const myFactory = ()=>({ + myStep: globalThis[Symbol.for("WORKFLOW_USE_STEP")]("step//input.js//myFactory/myStep") + }); +export default myFactory;