Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions packages/core/src/parse-name.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,22 @@ describe('parseWorkflowName', () => {
});
});

test('should handle Windows path with backslashes during workflow name normalization', () => {
// This tests the scenario from the bug report where the workflow name contains backslashes
const windowsWorkflowName = 'workflow//C:\\dev\\birthday-card-generator\\app\\api\\generate\\route.ts//handleOrder';
const normalizedName = windowsWorkflowName.replace(/\\/g, '/');

// The normalized name should equal the expected format
expect(normalizedName).toBe('workflow//C:/dev/birthday-card-generator/app/api/generate/route.ts//handleOrder');

const result = parseWorkflowName(normalizedName);
expect(result).toEqual({
shortName: 'handleOrder',
path: 'C:/dev/birthday-card-generator/app/api/generate/route.ts',
functionName: 'handleOrder',
});
});

test('should parse workflow name with nested function names', () => {
const result = parseWorkflowName(
'workflow//src/app.ts//nested//function//name'
Expand Down
27 changes: 27 additions & 0 deletions packages/core/src/workflow.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2303,5 +2303,32 @@ describe('runWorkflow', () => {
'sleep with date completed'
);
});

it('should handle Windows paths with backslashes in workflow names', async () => {
// Test the specific Windows path issue from the bug report
const workflowName = 'workflow//C:/dev/birthday-card-generator/app/api/generate/route.ts//handleOrder';
const workflowCode = `function handleOrder() { return "success from Windows"; }${getWorkflowTransformCode(workflowName)}`;

// Simulate the problematic workflow name with backslashes (as might occur on Windows)
const windowsWorkflowName = 'workflow//C:\\dev\\birthday-card-generator\\app\\api\\generate\\route.ts//handleOrder';

const ops: Promise<any>[] = [];
const workflowRun: WorkflowRun = {
runId: 'wrun_windows_test',
workflowName: windowsWorkflowName, // Use the backslash version
status: 'running',
input: dehydrateWorkflowArguments([], ops),
createdAt: new Date('2024-01-01T00:00:00.000Z'),
updatedAt: new Date('2024-01-01T00:00:00.000Z'),
startedAt: new Date('2024-01-01T00:00:00.000Z'),
deploymentId: 'test-deployment',
};

const events: Event[] = [];

// This should work now because the workflow.ts normalizes the name before lookup
const result = await runWorkflow(workflowCode, workflowRun, events);
expect(result).toBe("success from Windows");
});
});
});
9 changes: 7 additions & 2 deletions packages/core/src/workflow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -549,16 +549,21 @@ export async function runWorkflow(
const parsedName = parseWorkflowName(workflowRun.workflowName);
const filename = parsedName?.path || workflowRun.workflowName;

// Normalize the workflow name to handle Windows path separators
// The SWC transform normalizes paths to forward slashes during bundling,
// but the workflow name lookup might contain backslashes on Windows
const normalizedWorkflowName = workflowRun.workflowName.replace(/\\/g, '/');

const workflowFn = runInContext(
`${workflowCode}; globalThis.__private_workflows?.get(${JSON.stringify(workflowRun.workflowName)})`,
`${workflowCode}; globalThis.__private_workflows?.get(${JSON.stringify(normalizedWorkflowName)})`,
context,
{ filename }
);

if (typeof workflowFn !== 'function') {
throw new ReferenceError(
`Workflow ${JSON.stringify(
workflowRun.workflowName
normalizedWorkflowName
)} must be a function, but got "${typeof workflowFn}" instead`
);
}
Expand Down
Loading