Set workflowId property in workflow mode for non-exported workflow functions (#555)

### TL;DR

Modified the SWC plugin to set the `workflowId` property for all workflow functions in workflow mode, regardless of whether they are exported.

### What changed?

- Removed conditional logic that only added the `workflowId` property to exported workflow functions in workflow mode
- Now all workflow functions will have the `workflowId` property set, regardless of export status
- Updated test fixtures to reflect this change

### How to test?

1. Create a workflow file with non-exported workflow functions
2. Verify that the compiled output includes `workflowId` properties for all workflow functions
3. Run the existing test suite to ensure all tests pass with the updated behavior

### Why make this change?

This change ensures consistent behavior for all workflow functions. Previously, only exported workflow functions received the `workflowId` property in workflow mode, which could lead to inconsistent behavior when referencing non-exported workflow functions within the same file. This change makes the behavior more predictable and ensures all workflow functions are properly identified.
This commit is contained in:
Nathan Rajlich
2025-12-05 14:31:54 -08:00
committed by GitHub
parent fa37d26275
commit af5b005ac8
3 changed files with 25 additions and 56 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"@workflow/swc-plugin": patch
---
Set `workflowId` property in workflow mode for non-exported workflow functions
@@ -3503,27 +3503,6 @@ impl VisitMut for StepTransform {
}
}
// First pass: Collect names that are exported via `export { ... }` syntax
// This is needed to determine which non-exported workflow functions need workflowId in Workflow mode
let mut named_export_names: HashSet<String> = HashSet::new();
for item in items.iter() {
if let ModuleItem::ModuleDecl(ModuleDecl::ExportNamed(named)) = item {
// Only process local exports (not re-exports from other modules)
if named.src.is_none() {
for specifier in &named.specifiers {
if let ExportSpecifier::Named(named_spec) = specifier {
// Get the local name (the original identifier, not the exported alias)
let local_name = match &named_spec.orig {
ModuleExportName::Ident(ident) => ident.sym.to_string(),
ModuleExportName::Str(s) => s.value.to_string_lossy().to_string(),
};
named_export_names.insert(local_name);
}
}
}
}
}
// Process items and collect functions that need workflowId assignments
let mut items_to_insert = Vec::new();
@@ -3785,21 +3764,13 @@ impl VisitMut for StepTransform {
// Non-exported function declaration
let fn_name = fn_decl.ident.sym.to_string();
if self.workflow_function_names.contains(&fn_name) {
// In Client/Step modes: always add workflowId
// In Workflow mode: only add if later exported via `export { ... }`
let should_add = match self.mode {
TransformMode::Client | TransformMode::Step => true,
TransformMode::Workflow => named_export_names.contains(&fn_name),
};
if should_add {
items_to_insert.push((
i + 1,
ModuleItem::Stmt(self.create_workflow_id_assignment(
&fn_name,
fn_decl.function.span,
)),
));
}
items_to_insert.push((
i + 1,
ModuleItem::Stmt(self.create_workflow_id_assignment(
&fn_name,
fn_decl.function.span,
)),
));
}
}
ModuleItem::Stmt(Stmt::Decl(Decl::Var(var_decl))) => {
@@ -3808,26 +3779,18 @@ impl VisitMut for StepTransform {
if let Pat::Ident(binding) = &declarator.name {
let name = binding.id.sym.to_string();
if self.workflow_function_names.contains(&name) {
// In Client/Step modes: always add workflowId
// In Workflow mode: only add if later exported via `export { ... }`
let should_add = match self.mode {
TransformMode::Client | TransformMode::Step => true,
TransformMode::Workflow => named_export_names.contains(&name),
};
if should_add {
if let Some(init) = &declarator.init {
let span = match &**init {
Expr::Fn(fn_expr) => fn_expr.function.span,
Expr::Arrow(arrow_expr) => arrow_expr.span,
_ => declarator.span,
};
items_to_insert.push((
i + 1,
ModuleItem::Stmt(
self.create_workflow_id_assignment(&name, span),
),
));
}
if let Some(init) = &declarator.init {
let span = match &**init {
Expr::Fn(fn_expr) => fn_expr.function.span,
Expr::Arrow(arrow_expr) => arrow_expr.span,
_ => declarator.span,
};
items_to_insert.push((
i + 1,
ModuleItem::Stmt(
self.create_workflow_id_assignment(&name, span),
),
));
}
}
}
@@ -18,6 +18,7 @@ defaultWorkflow.workflowId = "workflow//input.js//defaultWorkflow";
async function internalWorkflow() {
return 'internal';
}
internalWorkflow.workflowId = "workflow//input.js//internalWorkflow";
// Use the internal workflow to avoid lint warning
regularFunction(internalWorkflow);
// Regular function should not be affected