1// Alchemy modifications are licensed under Apache-2.0.
2// This file includes third-party code; see /THIRD_PARTY_LICENSES.md.
3import { WorkerEntrypoint } from "cloudflare:workers";
4import type { WorkflowEvent, WorkflowStep } from "cloudflare:workers";
5
6// Test entry point — re-exports everything from src/index.ts and adds
7// a TestWorkflow class that can be bound as USER_WORKFLOW via serviceBindings.
8// This allows the workflow entrypoint to survive DO aborts (unlike the old
9// setWorkflowEntrypoint pattern which manually mutated instance.env).
10//
11// NOTE: We extend WorkerEntrypoint (not WorkflowEntrypoint) because workerd
12// only recognises WorkerEntrypoint subclasses for service-binding RPC.
13// WorkflowEntrypoint is a higher-level abstraction used by the Workflows
14// platform; for our test harness the engine just needs a target with a
15// callable run() method.
16
17export * from "../index.ts";
18
19type WorkflowCallback = (
20 event: unknown,
21 step: WorkflowStep,
22) => Promise<unknown>;
23
24let __testWorkflowCallback: WorkflowCallback | undefined;
25
26/**
27 * Set the workflow callback that TestWorkflow.run() will delegate to.
28 * Call this before creating or restarting a workflow instance in tests.
29 */
30export function setTestWorkflowCallback(
31 cb: WorkflowCallback | undefined,
32): void {
33 __testWorkflowCallback = cb;
34}
35
36/**
37 * A WorkerEntrypoint subclass for tests that delegates run() to a
38 * module-level callback. Configured as the USER_WORKFLOW service binding
39 * in vitest.config.ts so it survives DO aborts (unlike manual env injection).
40 */
41export class TestWorkflow extends WorkerEntrypoint {
42 async run(
43 event: Readonly<WorkflowEvent<unknown>>,
44 step: WorkflowStep,
45 ): Promise<unknown> {
46 if (!__testWorkflowCallback) {
47 throw new Error(
48 "TestWorkflow callback not set — call setTestWorkflowCallback() before running the workflow",
49 );
50 }
51 return await __testWorkflowCallback(event, step);
52 }
53}